From 00fe8a7b2317f11bff754c73a87b69445fe0b33d Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 03:18:59 +0000 Subject: Merged revisions 72912,72920,72940 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72912 | benjamin.peterson | 2009-05-25 08:13:44 -0500 (Mon, 25 May 2009) | 5 lines add a SETUP_WITH opcode It speeds up the with statement and correctly looks up the special methods involved. ........ r72920 | benjamin.peterson | 2009-05-25 15:12:57 -0500 (Mon, 25 May 2009) | 1 line take into account the fact that SETUP_WITH pushes a finally block ........ r72940 | benjamin.peterson | 2009-05-26 07:49:59 -0500 (Tue, 26 May 2009) | 1 line teach the peepholer about SETUP_WITH ........ --- Python/compile.c | 73 +++++++------------------------------------------------- 1 file changed, 9 insertions(+), 64 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index c78949d887..490137f3db 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -761,6 +761,8 @@ opcode_stack_effect(int opcode, int oparg) return -1; case BREAK_LOOP: return 0; + case SETUP_WITH: + return 7; case WITH_CLEANUP: return -1; /* XXX Sometimes more */ case STORE_LOCALS: @@ -3085,85 +3087,31 @@ expr_constant(expr_ty e) static int compiler_with(struct compiler *c, stmt_ty s) { - static identifier enter_attr, exit_attr; basicblock *block, *finally; - identifier tmpvalue = NULL, tmpexit = NULL; assert(s->kind == With_kind); - if (!enter_attr) { - enter_attr = PyUnicode_InternFromString("__enter__"); - if (!enter_attr) - return 0; - } - if (!exit_attr) { - exit_attr = PyUnicode_InternFromString("__exit__"); - if (!exit_attr) - return 0; - } - block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) return 0; - if (s->v.With.optional_vars) { - /* Create a temporary variable to hold context.__enter__(). - We need to do this rather than preserving it on the stack - because SETUP_FINALLY remembers the stack level. - We need to do the assignment *inside* the try/finally - so that context.__exit__() is called when the assignment - fails. But we need to call context.__enter__() *before* - the try/finally so that if it fails we won't call - context.__exit__(). - */ - tmpvalue = compiler_new_tmpname(c); - if (tmpvalue == NULL) - return 0; - PyArena_AddPyObject(c->c_arena, tmpvalue); - } - tmpexit = compiler_new_tmpname(c); - if (tmpexit == NULL) - return 0; - PyArena_AddPyObject(c->c_arena, tmpexit); - /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); + ADDOP_JREL(c, SETUP_WITH, finally); - /* Squirrel away context.__exit__ by stuffing it under context */ - ADDOP(c, DUP_TOP); - ADDOP_O(c, LOAD_ATTR, exit_attr, names); - if (!compiler_nameop(c, tmpexit, Store)) - return 0; - - /* Call context.__enter__() */ - ADDOP_O(c, LOAD_ATTR, enter_attr, names); - ADDOP_I(c, CALL_FUNCTION, 0); - - if (s->v.With.optional_vars) { - /* Store it in tmpvalue */ - if (!compiler_nameop(c, tmpvalue, Store)) - return 0; - } - else { - /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); - } - - /* Start the try block */ - ADDOP_JREL(c, SETUP_FINALLY, finally); - + /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); if (!compiler_push_fblock(c, FINALLY_TRY, block)) { return 0; } if (s->v.With.optional_vars) { - /* Bind saved result of context.__enter__() to VAR */ - if (!compiler_nameop(c, tmpvalue, Load) || - !compiler_nameop(c, tmpvalue, Del)) - return 0; - VISIT(c, expr, s->v.With.optional_vars); + VISIT(c, expr, s->v.With.optional_vars); + } + else { + /* Discard result from context.__enter__() */ + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3181,9 +3129,6 @@ compiler_with(struct compiler *c, stmt_ty s) /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic opcode. */ - if (!compiler_nameop(c, tmpexit, Load) || - !compiler_nameop(c, tmpexit, Del)) - return 0; ADDOP(c, WITH_CLEANUP); /* Finally block ends. */ -- cgit v1.2.1 From 4506d5bfb7ba4ce67acadb33e5b3ea4f18937be6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 17:22:03 +0000 Subject: Merged revisions 73004,73439,73496,73509,73529,73564,73576-73577,73595-73596,73605 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73004 | jeffrey.yasskin | 2009-05-28 22:44:31 -0500 (Thu, 28 May 2009) | 5 lines Fix nearly all compilation warnings under Apple gcc-4.0. Tested with OPT="-g -Wall -Wstrict-prototypes -Werror" in both --with-pydebug mode and --without. There's still a batch of non-prototype warnings in Xlib.h that I don't know how to fix. ........ r73439 | benjamin.peterson | 2009-06-15 19:29:31 -0500 (Mon, 15 Jun 2009) | 1 line don't mask encoding errors when decoding a string #6289 ........ r73496 | vinay.sajip | 2009-06-21 12:37:27 -0500 (Sun, 21 Jun 2009) | 1 line Issue #6314: logging.basicConfig() performs extra checks on the "level" argument. ........ r73509 | amaury.forgeotdarc | 2009-06-22 14:33:48 -0500 (Mon, 22 Jun 2009) | 2 lines #4490 Fix sample code run by "python -m xml.sax.xmlreader" ........ r73529 | r.david.murray | 2009-06-23 13:02:46 -0500 (Tue, 23 Jun 2009) | 4 lines Fix issue 5230 by having pydoc's safeimport check to see if the import error was thrown from itself in order to decide if the module can't be found. Thanks to Lucas Prado Melo for collaborating on the fix and tests. ........ r73564 | amaury.forgeotdarc | 2009-06-25 17:29:29 -0500 (Thu, 25 Jun 2009) | 6 lines #2016 Fix a crash in function call when the **kwargs dictionary is mutated during the function call setup. This even gives a slight speedup, probably because tuple allocation is faster than PyMem_NEW. ........ r73576 | benjamin.peterson | 2009-06-26 18:37:06 -0500 (Fri, 26 Jun 2009) | 1 line document is_declared_global() ........ r73577 | benjamin.peterson | 2009-06-27 09:16:23 -0500 (Sat, 27 Jun 2009) | 1 line link to extensive generator docs in the reference manual ........ r73595 | ezio.melotti | 2009-06-27 18:45:39 -0500 (Sat, 27 Jun 2009) | 1 line stmt and setup can contain multiple statements, see #5896 ........ r73596 | ezio.melotti | 2009-06-27 19:07:45 -0500 (Sat, 27 Jun 2009) | 1 line Fixed a wrong apostrophe ........ r73605 | georg.brandl | 2009-06-28 07:10:18 -0500 (Sun, 28 Jun 2009) | 1 line Remove stray pychecker directive. ........ --- Python/compile.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 490137f3db..f048743701 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -551,18 +551,6 @@ compiler_exit_scope(struct compiler *c) } -/* Allocate a new "anonymous" local variable. - Used by list comprehensions and with statements. -*/ - -static PyObject * -compiler_new_tmpname(struct compiler *c) -{ - char tmpname[256]; - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); - return PyUnicode_FromString(tmpname); -} - /* Allocate a new block and return a pointer to it. Returns NULL on error. */ -- cgit v1.2.1 From fdeceae09c9611b47d4b7b031b6b602c38913e88 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 28 Jun 2009 19:19:51 +0000 Subject: Merged revisions 73376,73393,73398,73400,73404-73405,73409,73419-73421,73432,73457,73460,73485-73486,73488-73489,73501-73502,73513-73514 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73376 | benjamin.peterson | 2009-06-11 17:29:23 -0500 (Thu, 11 Jun 2009) | 1 line remove check for case handled in sub-function ........ r73393 | alexandre.vassalotti | 2009-06-12 13:56:57 -0500 (Fri, 12 Jun 2009) | 2 lines Clear reference to the static PyExc_RecursionErrorInst in _PyExc_Fini. ........ r73398 | alexandre.vassalotti | 2009-06-12 15:57:12 -0500 (Fri, 12 Jun 2009) | 3 lines Add const qualifier to PyErr_SetFromErrnoWithFilename and to PyErr_SetFromErrnoWithUnicodeFilename. ........ r73400 | alexandre.vassalotti | 2009-06-12 16:43:47 -0500 (Fri, 12 Jun 2009) | 2 lines Delete outdated make file for building the parser with MSVC 6. ........ r73404 | benjamin.peterson | 2009-06-12 20:40:00 -0500 (Fri, 12 Jun 2009) | 1 line keep the slice.step field as NULL if no step expression is given ........ r73405 | benjamin.peterson | 2009-06-12 22:46:30 -0500 (Fri, 12 Jun 2009) | 1 line prevent import statements from assigning to None ........ r73409 | benjamin.peterson | 2009-06-13 08:06:21 -0500 (Sat, 13 Jun 2009) | 1 line allow importing from a module named None if it has an 'as' clause ........ r73419 | benjamin.peterson | 2009-06-13 11:19:19 -0500 (Sat, 13 Jun 2009) | 1 line set Print.values to NULL if there are no values ........ r73420 | benjamin.peterson | 2009-06-13 12:08:53 -0500 (Sat, 13 Jun 2009) | 1 line give a better error message when deleting () ........ r73421 | benjamin.peterson | 2009-06-13 15:23:33 -0500 (Sat, 13 Jun 2009) | 1 line when no module is given in a 'from' relative import, make ImportFrom.module NULL ........ r73432 | amaury.forgeotdarc | 2009-06-14 16:20:40 -0500 (Sun, 14 Jun 2009) | 3 lines #6227: Because of a wrong indentation, the test was not testing what it should. Ensure that the snippet in doctest_aliases actually contains aliases. ........ r73457 | benjamin.peterson | 2009-06-16 18:13:09 -0500 (Tue, 16 Jun 2009) | 1 line add underscores ........ r73460 | benjamin.peterson | 2009-06-16 22:23:04 -0500 (Tue, 16 Jun 2009) | 1 line remove unused 'encoding' member from the compiler struct ........ r73485 | benjamin.peterson | 2009-06-19 17:07:47 -0500 (Fri, 19 Jun 2009) | 1 line remove duplicate test ........ r73486 | benjamin.peterson | 2009-06-19 17:09:17 -0500 (Fri, 19 Jun 2009) | 1 line add missing assertion #6313 ........ r73488 | benjamin.peterson | 2009-06-19 17:16:28 -0500 (Fri, 19 Jun 2009) | 1 line show that this one isn't used ........ r73489 | benjamin.peterson | 2009-06-19 17:21:12 -0500 (Fri, 19 Jun 2009) | 1 line use closures ........ r73501 | benjamin.peterson | 2009-06-21 18:01:07 -0500 (Sun, 21 Jun 2009) | 1 line don't need to add the name 'lambda' as assigned ........ r73502 | benjamin.peterson | 2009-06-21 18:03:36 -0500 (Sun, 21 Jun 2009) | 1 line remove tmpname support since it's no longer used ........ r73513 | benjamin.peterson | 2009-06-22 20:18:57 -0500 (Mon, 22 Jun 2009) | 1 line fix grammar ........ r73514 | benjamin.peterson | 2009-06-22 22:01:56 -0500 (Mon, 22 Jun 2009) | 1 line remove some unused symtable constants ........ --- Python/compile.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index f048743701..787dfe37d0 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -117,7 +117,6 @@ struct compiler_unit { members, you can reach all early allocated blocks. */ basicblock *u_blocks; basicblock *u_curblock; /* pointer to current block */ - int u_tmpname; /* temporary variables for list comps */ int u_nfblocks; struct fblockinfo u_fblock[CO_MAXBLOCKS]; @@ -146,7 +145,6 @@ struct compiler { struct compiler_unit *u; /* compiler state for current block */ PyObject *c_stack; /* Python list holding compiler_unit ptrs */ - char *c_encoding; /* source encoding (a borrowed reference) */ PyArena *c_arena; /* pointer to memory allocation arena */ }; @@ -295,9 +293,6 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, goto finally; } - /* XXX initialize to NULL for now, need to handle */ - c.c_encoding = NULL; - co = compiler_mod(&c, mod); finally: @@ -488,7 +483,6 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, } u->u_blocks = NULL; - u->u_tmpname = 0; u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; @@ -2154,6 +2148,13 @@ compiler_from_import(struct compiler *c, stmt_ty s) PyObject *names = PyTuple_New(n); PyObject *level; + static PyObject *empty_string; + + if (!empty_string) { + empty_string = PyUnicode_FromString(""); + if (!empty_string) + return 0; + } if (!names) return 0; @@ -2171,23 +2172,24 @@ compiler_from_import(struct compiler *c, stmt_ty s) PyTuple_SET_ITEM(names, i, alias->name); } - if (s->lineno > c->c_future->ff_lineno) { - if (!PyUnicode_CompareWithASCIIString(s->v.ImportFrom.module, - "__future__")) { - Py_DECREF(level); - Py_DECREF(names); - return compiler_error(c, - "from __future__ imports must occur " + if (s->lineno > c->c_future->ff_lineno && s->v.ImportFrom.module && + !PyUnicode_CompareWithASCIIString(s->v.ImportFrom.module, "__future__")) { + Py_DECREF(level); + Py_DECREF(names); + return compiler_error(c, "from __future__ imports must occur " "at the beginning of the file"); - - } } ADDOP_O(c, LOAD_CONST, level, consts); Py_DECREF(level); ADDOP_O(c, LOAD_CONST, names, consts); Py_DECREF(names); - ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + if (s->v.ImportFrom.module) { + ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + } + else { + ADDOP_NAME(c, IMPORT_NAME, empty_string, names); + } for (i = 0; i < n; i++) { alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); identifier store_name; -- cgit v1.2.1 From db593b8be650afd6104f8fe478e8573ee6c6264d Mon Sep 17 00:00:00 2001 From: Alexandre Vassalotti Date: Tue, 21 Jul 2009 04:30:03 +0000 Subject: Merged revisions 72487-72488,72879 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72487 | jeffrey.yasskin | 2009-05-08 17:51:06 -0400 (Fri, 08 May 2009) | 7 lines PyCode_NewEmpty: Most uses of PyCode_New found by http://www.google.com/codesearch?q=PyCode_New are trying to build an empty code object, usually to put it in a dummy frame object. This patch adds a PyCode_NewEmpty wrapper which lets the user specify just the filename, function name, and first line number, instead of also requiring lots of code internals. ........ r72488 | jeffrey.yasskin | 2009-05-08 18:23:21 -0400 (Fri, 08 May 2009) | 13 lines Issue 5954, PyFrame_GetLineNumber: Most uses of PyCode_Addr2Line (http://www.google.com/codesearch?q=PyCode_Addr2Line) are just trying to get the line number of a specified frame, but there's no way to do that directly. Forcing people to go through the code object makes them know more about the guts of the interpreter than they should need. The remaining uses of PyCode_Addr2Line seem to be getting the line from a traceback (for example, http://www.google.com/codesearch/p?hl=en#u_9_nDrchrw/pygame-1.7.1release/src/base.c&q=PyCode_Addr2Line), which is replaced by the tb_lineno field. So we may be able to deprecate PyCode_Addr2Line entirely for external use. ........ r72879 | jeffrey.yasskin | 2009-05-23 19:23:01 -0400 (Sat, 23 May 2009) | 14 lines Issue #6042: lnotab-based tracing is very complicated and isn't documented very well. There were at least 3 comment blocks purporting to document co_lnotab, and none did a very good job. This patch unifies them into Objects/lnotab_notes.txt which tries to completely capture the current state of affairs. I also discovered that we've attached 2 layers of patches to the basic tracing scheme. The first layer avoids jumping to instructions that don't start a line, to avoid problems in if statements and while loops. The second layer discovered that jumps backward do need to trace at instructions that don't start a line, so it added extra lnotab entries for 'while' and 'for' loops, and added a special case for backward jumps within the same line. I replaced these patches by just treating forward and backward jumps differently. ........ --- Python/compile.c | 54 +++--------------------------------------------------- 1 file changed, 3 insertions(+), 51 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 787dfe37d0..24975b64a7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1748,9 +1748,6 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); compiler_use_next_block(c, start); - /* for expressions must be traced on each iteration, - so we need to set an extra line number. */ - c->u->u_lineno_set = 0; ADDOP_JREL(c, FOR_ITER, cleanup); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); @@ -1796,9 +1793,6 @@ compiler_while(struct compiler *c, stmt_ty s) if (!compiler_push_fblock(c, LOOP, loop)) return 0; if (constant == -1) { - /* while expressions must be traced on each iteration, - so we need to set an extra line number. */ - c->u->u_lineno_set = 0; VISIT(c, expr, s->v.While.test); ADDOP_JABS(c, POP_JUMP_IF_FALSE, anchor); } @@ -3654,51 +3648,9 @@ blocksize(basicblock *b) return size; } -/* All about a_lnotab. - -c_lnotab is an array of unsigned bytes disguised as a Python string. -It is used to map bytecode offsets to source code line #s (when needed -for tracebacks). - -The array is conceptually a list of - (bytecode offset increment, line number increment) -pairs. The details are important and delicate, best illustrated by example: - - byte code offset source code line number - 0 1 - 6 2 - 50 7 - 350 307 - 361 308 - -The first trick is that these numbers aren't stored, only the increments -from one row to the next (this doesn't really work, but it's a start): - - 0, 1, 6, 1, 44, 5, 300, 300, 11, 1 - -The second trick is that an unsigned byte can't hold negative values, or -values larger than 255, so (a) there's a deep assumption that byte code -offsets and their corresponding line #s both increase monotonically, and (b) -if at least one column jumps by more than 255 from one row to the next, more -than one pair is written to the table. In case #b, there's no way to know -from looking at the table later how many were written. That's the delicate -part. A user of c_lnotab desiring to find the source line number -corresponding to a bytecode address A should do something like this - - lineno = addr = 0 - for addr_incr, line_incr in c_lnotab: - addr += addr_incr - if addr > A: - return lineno - lineno += line_incr - -In order for this to work, when the addr field increments by more than 255, -the line # increment in each pair generated must be 0 until the remaining addr -increment is < 256. So, in the example above, assemble_lnotab (it used -to be called com_set_lineno) should not (as was actually done until 2.2) -expand 300, 300 to 255, 255, 45, 45, - but to 255, 0, 45, 255, 0, 45. -*/ +/* Appends a pair to the end of the line number table, a_lnotab, representing + the instruction's bytecode offset and line number. See + Objects/lnotab_notes.txt for the description of the line number table. */ static int assemble_lnotab(struct assembler *a, struct instr *i) -- cgit v1.2.1 From f960e3d89e9df749e709998d6d0d12d962224132 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Wed, 14 Oct 2009 19:14:38 +0000 Subject: Issue #1754094: Improve the stack depth calculation in the compiler. There should be no other effect than a small decrease in memory use. --- Python/compile.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 24975b64a7..d06a03b907 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -772,7 +772,7 @@ opcode_stack_effect(int opcode, int oparg) case UNPACK_EX: return (oparg&0xFF) + (oparg>>8); case FOR_ITER: - return 1; + return 1; /* or -1, at end of iterator */ case STORE_ATTR: return -2; @@ -799,7 +799,7 @@ opcode_stack_effect(int opcode, int oparg) case COMPARE_OP: return -1; case IMPORT_NAME: - return 0; + return -1; case IMPORT_FROM: return 1; @@ -3546,7 +3546,7 @@ dfs(struct compiler *c, basicblock *b, struct assembler *a) static int stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) { - int i; + int i, target_depth; struct instr *instr; if (b->b_seen || b->b_startdepth >= depth) return maxdepth; @@ -3559,8 +3559,17 @@ stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) maxdepth = depth; assert(depth >= 0); /* invalid code or bug in stackdepth() */ if (instr->i_jrel || instr->i_jabs) { + target_depth = depth; + if (instr->i_opcode == FOR_ITER) { + target_depth = depth-2; + } else if (instr->i_opcode == SETUP_FINALLY || + instr->i_opcode == SETUP_EXCEPT) { + target_depth = depth+3; + if (target_depth > maxdepth) + maxdepth = target_depth; + } maxdepth = stackdepth_walk(c, instr->i_target, - depth, maxdepth); + target_depth, maxdepth); if (instr->i_opcode == JUMP_ABSOLUTE || instr->i_opcode == JUMP_FORWARD) { goto out; /* remaining code is dead */ -- cgit v1.2.1 From 26d8fbd945451134d1527e2367c436e01395e0c6 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 15 Oct 2009 19:55:18 +0000 Subject: Merged revisions 75440 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75440 | mark.dickinson | 2009-10-15 18:45:39 +0100 (Thu, 15 Oct 2009) | 1 line Allow core Python build to succeed under WITHOUT_COMPLEX. The module build stage still fails. ........ --- Python/compile.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index d06a03b907..081268bcac 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -895,10 +895,8 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) { PyObject *t, *v; Py_ssize_t arg; - unsigned char *p, *q; - Py_complex z; + unsigned char *p; double d; - int real_part_zero, imag_part_zero; /* necessary to make sure types aren't coerced (e.g., int and long) */ /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ @@ -913,7 +911,11 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) else t = PyTuple_Pack(2, o, o->ob_type); } +#ifndef WITHOUT_COMPLEX else if (PyComplex_Check(o)) { + Py_complex z; + int real_part_zero, imag_part_zero; + unsigned char *q; /* complex case is even messier: we need to make complex(x, 0.) different from complex(x, -0.) and complex(0., y) different from complex(-0., y), for any x and y. In @@ -943,6 +945,7 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) t = PyTuple_Pack(2, o, o->ob_type); } } +#endif /* WITHOUT_COMPLEX */ else { t = PyTuple_Pack(2, o, o->ob_type); } -- cgit v1.2.1 From e4216a84485c97ae3ff3c9fcd27feba89513fc27 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sun, 18 Oct 2009 16:41:32 +0000 Subject: Remove the uses of WITHOUT_COMPLEX introduced in r75471 --- 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 081268bcac..2bb9beb3d8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -911,7 +911,6 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) else t = PyTuple_Pack(2, o, o->ob_type); } -#ifndef WITHOUT_COMPLEX else if (PyComplex_Check(o)) { Py_complex z; int real_part_zero, imag_part_zero; @@ -945,7 +944,6 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) t = PyTuple_Pack(2, o, o->ob_type); } } -#endif /* WITHOUT_COMPLEX */ else { t = PyTuple_Pack(2, o, o->ob_type); } -- cgit v1.2.1 From 7e20442f707b90d4d2eb0b47eabe9b29b923103e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 25 Nov 2009 17:46:26 +0000 Subject: Merged revisions 75264,75268,75293,75318,75391-75392,75436,75478,75971,76003,76058,76140-76141,76231,76380,76428-76429 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r75264 | andrew.kuchling | 2009-10-05 17:30:22 -0500 (Mon, 05 Oct 2009) | 1 line Add various items ........ r75268 | andrew.kuchling | 2009-10-05 17:45:39 -0500 (Mon, 05 Oct 2009) | 1 line Remove two notes ........ r75293 | kristjan.jonsson | 2009-10-09 09:32:19 -0500 (Fri, 09 Oct 2009) | 2 lines http://bugs.python.org/issue7029 a non-default timer wasn't actually used by the individual Tests. ........ r75318 | benjamin.peterson | 2009-10-10 16:15:58 -0500 (Sat, 10 Oct 2009) | 1 line remove script which uses long gone module ........ r75391 | andrew.kuchling | 2009-10-13 10:49:33 -0500 (Tue, 13 Oct 2009) | 1 line Link to PEP ........ r75392 | andrew.kuchling | 2009-10-13 11:11:49 -0500 (Tue, 13 Oct 2009) | 1 line Various link, textual, and markup fixes ........ r75436 | benjamin.peterson | 2009-10-15 10:39:15 -0500 (Thu, 15 Oct 2009) | 1 line don't need to mess up sys.path ........ r75478 | senthil.kumaran | 2009-10-17 20:58:45 -0500 (Sat, 17 Oct 2009) | 3 lines Fix a typo. ........ r75971 | benjamin.peterson | 2009-10-30 22:56:15 -0500 (Fri, 30 Oct 2009) | 1 line add some checks for evaluation order with parenthesis #7210 ........ r76003 | antoine.pitrou | 2009-10-31 19:30:13 -0500 (Sat, 31 Oct 2009) | 6 lines Hopefully fix the buildbot problems on test_mailbox, by computing the maildir toc cache refresh date before actually refreshing the cache. (see #6896) ........ r76058 | benjamin.peterson | 2009-11-02 10:14:19 -0600 (Mon, 02 Nov 2009) | 1 line grant list.index() a more informative error message #7252 ........ r76140 | nick.coghlan | 2009-11-07 02:13:55 -0600 (Sat, 07 Nov 2009) | 1 line Add test for runpy.run_module package execution and use something other than logging as the example of a non-executable package ........ r76141 | nick.coghlan | 2009-11-07 02:15:01 -0600 (Sat, 07 Nov 2009) | 1 line Some minor cleanups to private runpy code and docstrings ........ r76231 | benjamin.peterson | 2009-11-12 17:42:23 -0600 (Thu, 12 Nov 2009) | 1 line this main is much more useful ........ r76380 | antoine.pitrou | 2009-11-18 14:20:46 -0600 (Wed, 18 Nov 2009) | 3 lines Mention Giampolo R's new FTP TLS support in the what's new file ........ r76428 | benjamin.peterson | 2009-11-19 20:15:50 -0600 (Thu, 19 Nov 2009) | 1 line turn goto into do while loop ........ r76429 | benjamin.peterson | 2009-11-19 20:56:43 -0600 (Thu, 19 Nov 2009) | 2 lines avoid doing an uneeded import in a function ........ --- Python/compile.c | 67 ++++++++++++++++++++++++++------------------------------ 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 2bb9beb3d8..d8fb47b16e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3802,49 +3802,47 @@ static void assemble_jump_offsets(struct assembler *a, struct compiler *c) { basicblock *b; - int bsize, totsize, extended_arg_count, last_extended_arg_count = 0; + int bsize, totsize, extended_arg_count = 0, last_extended_arg_count; int i; /* Compute the size of each block and fixup jump args. Replace block pointer with position in bytecode. */ -start: - totsize = 0; - for (i = a->a_nblocks - 1; i >= 0; i--) { - b = a->a_postorder[i]; - bsize = blocksize(b); - b->b_offset = totsize; - totsize += bsize; - } - extended_arg_count = 0; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - bsize = b->b_offset; - for (i = 0; i < b->b_iused; i++) { - struct instr *instr = &b->b_instr[i]; - /* Relative jumps are computed relative to - the instruction pointer after fetching - the jump instruction. - */ - bsize += instrsize(instr); - if (instr->i_jabs) - instr->i_oparg = instr->i_target->b_offset; - else if (instr->i_jrel) { - int delta = instr->i_target->b_offset - bsize; - instr->i_oparg = delta; + do { + totsize = 0; + for (i = a->a_nblocks - 1; i >= 0; i--) { + b = a->a_postorder[i]; + bsize = blocksize(b); + b->b_offset = totsize; + totsize += bsize; + } + last_extended_arg_count = extended_arg_count; + extended_arg_count = 0; + for (b = c->u->u_blocks; b != NULL; b = b->b_list) { + bsize = b->b_offset; + for (i = 0; i < b->b_iused; i++) { + struct instr *instr = &b->b_instr[i]; + /* Relative jumps are computed relative to + the instruction pointer after fetching + the jump instruction. + */ + bsize += instrsize(instr); + if (instr->i_jabs) + instr->i_oparg = instr->i_target->b_offset; + else if (instr->i_jrel) { + int delta = instr->i_target->b_offset - bsize; + instr->i_oparg = delta; + } + else + continue; + if (instr->i_oparg > 0xffff) + extended_arg_count++; } - else - continue; - if (instr->i_oparg > 0xffff) - extended_arg_count++; } - } /* XXX: This is an awful hack that could hurt performance, but on the bright side it should work until we come up with a better solution. - In the meantime, should the goto be dropped in favor - of a loop? - The issue is that in the first loop blocksize() is called which calls instrsize() which requires i_oparg be set appropriately. There is a bootstrap problem because @@ -3855,10 +3853,7 @@ start: ones in jump instructions. So this should converge fairly quickly. */ - if (last_extended_arg_count != extended_arg_count) { - last_extended_arg_count = extended_arg_count; - goto start; - } + } while (last_extended_arg_count != extended_arg_count); } static PyObject * -- cgit v1.2.1 From a83432f18258ffa6e3431fba960353cbe4a1b5b7 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Sat, 28 Nov 2009 16:38:16 +0000 Subject: Merged revisions 76575 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r76575 | mark.dickinson | 2009-11-28 16:32:27 +0000 (Sat, 28 Nov 2009) | 5 lines Issue #1678380: When distinguishing between -0.0 and 0.0 in compiler_add_o, use copysign instead of examining the first and last bytes of the double. The latter method fails for little-endian ARM, OABI, where doubles are little-endian but with the words swapped. ........ --- Python/compile.c | 45 +++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index d8fb47b16e..2c58d449b5 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -895,50 +895,39 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) { PyObject *t, *v; Py_ssize_t arg; - unsigned char *p; double d; /* necessary to make sure types aren't coerced (e.g., int and long) */ /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ if (PyFloat_Check(o)) { d = PyFloat_AS_DOUBLE(o); - p = (unsigned char*) &d; /* all we need is to make the tuple different in either the 0.0 * or -0.0 case from all others, just to avoid the "coercion". */ - if (*p==0 && p[sizeof(double)-1]==0) + if (d == 0.0 && copysign(1.0, d) < 0.0) t = PyTuple_Pack(3, o, o->ob_type, Py_None); else t = PyTuple_Pack(2, o, o->ob_type); } else if (PyComplex_Check(o)) { Py_complex z; - int real_part_zero, imag_part_zero; - unsigned char *q; - /* complex case is even messier: we need to make complex(x, - 0.) different from complex(x, -0.) and complex(0., y) - different from complex(-0., y), for any x and y. In - particular, all four complex zeros should be - distinguished.*/ + int real_negzero, imag_negzero; + /* For the complex case we must make complex(x, 0.) + different from complex(x, -0.) and complex(0., y) + different from complex(-0., y), for any x and y. + All four complex zeros must be distinguished.*/ z = PyComplex_AsCComplex(o); - p = (unsigned char*) &(z.real); - q = (unsigned char*) &(z.imag); - /* all that matters here is that on IEEE platforms - real_part_zero will be true if z.real == 0., and false if - z.real == -0. In fact, real_part_zero will also be true - for some other rarely occurring nonzero floats, but this - doesn't matter. Similar comments apply to - imag_part_zero. */ - real_part_zero = *p==0 && p[sizeof(double)-1]==0; - imag_part_zero = *q==0 && q[sizeof(double)-1]==0; - if (real_part_zero && imag_part_zero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_True); - } - else if (real_part_zero && !imag_part_zero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_True, Py_False); - } - else if (!real_part_zero && imag_part_zero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_False, Py_True); + real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; + imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; + if (real_negzero && imag_negzero) { + t = PyTuple_Pack(5, o, o->ob_type, + Py_None, Py_None, Py_None); + } + else if (imag_negzero) { + t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); + } + else if (real_negzero) { + t = PyTuple_Pack(3, o, o->ob_type, Py_None); } else { t = PyTuple_Pack(2, o, o->ob_type); -- cgit v1.2.1 From 54c1aa548c9e58d197a9954e8ce8e39062441226 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 17 Mar 2010 20:56:58 +0000 Subject: Merged revisions 79034 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79034 | benjamin.peterson | 2010-03-17 15:41:42 -0500 (Wed, 17 Mar 2010) | 1 line prevent lambda functions from having docstrings #8164 ........ --- Python/compile.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 2c58d449b5..62fa46c615 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1660,6 +1660,11 @@ compiler_lambda(struct compiler *c, expr_ty e) if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) return 0; + /* Make None the first constant, so the lambda can't have a + docstring. */ + if (compiler_add_o(c, c->u->u_consts, Py_None) < 0) + return 0; + c->u->u_argcount = asdl_seq_LEN(args->args); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); -- cgit v1.2.1 From 567b94adaaceb622c33f9be1998735dfb95f1707 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 9 May 2010 15:52:27 +0000 Subject: Recorded merge of revisions 81029 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines Untabify C files. Will watch buildbots. ........ --- Python/compile.c | 6416 +++++++++++++++++++++++++++--------------------------- 1 file changed, 3208 insertions(+), 3208 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 62fa46c615..fa7dcef5fb 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -5,10 +5,10 @@ * PyCodeObject. The compiler makes several passes to build the code * object: * 1. Checks for future statements. See future.c - * 2. Builds a symbol table. See symtable.c. + * 2. Builds a symbol table. See symtable.c. * 3. Generate code for basic blocks. See compiler_mod() in this file. * 4. Assemble the basic blocks into final code. See assemble() in - * this file. + * this file. * 5. Optimize the byte code (peephole optimizations). See peephole.c * * Note that compiler_mod() suggests module, but the module ast type @@ -45,37 +45,37 @@ int Py_OptimizeFlag = 0; #define COMP_DICTCOMP 3 struct instr { - unsigned i_jabs : 1; - unsigned i_jrel : 1; - unsigned i_hasarg : 1; - unsigned char i_opcode; - int i_oparg; - struct basicblock_ *i_target; /* target block (if jump instruction) */ - int i_lineno; + unsigned i_jabs : 1; + unsigned i_jrel : 1; + unsigned i_hasarg : 1; + unsigned char i_opcode; + int i_oparg; + struct basicblock_ *i_target; /* target block (if jump instruction) */ + int i_lineno; }; typedef struct basicblock_ { /* Each basicblock in a compilation unit is linked via b_list in the reverse order that the block are allocated. b_list points to the next block, not to be confused with b_next, which is next by control flow. */ - struct basicblock_ *b_list; - /* number of instructions used */ - int b_iused; - /* length of instruction array (b_instr) */ - int b_ialloc; - /* pointer to an array of instructions, initially NULL */ - struct instr *b_instr; - /* If b_next is non-NULL, it is a pointer to the next - block reached by normal control flow. */ - struct basicblock_ *b_next; - /* b_seen is used to perform a DFS of basicblocks. */ - unsigned b_seen : 1; - /* b_return is true if a RETURN_VALUE opcode is inserted. */ - unsigned b_return : 1; - /* depth of stack upon entry of block, computed by stackdepth() */ - int b_startdepth; - /* instruction offset for block, computed by assemble_jump_offsets() */ - int b_offset; + struct basicblock_ *b_list; + /* number of instructions used */ + int b_iused; + /* length of instruction array (b_instr) */ + int b_ialloc; + /* pointer to an array of instructions, initially NULL */ + struct instr *b_instr; + /* If b_next is non-NULL, it is a pointer to the next + block reached by normal control flow. */ + struct basicblock_ *b_next; + /* b_seen is used to perform a DFS of basicblocks. */ + unsigned b_seen : 1; + /* b_return is true if a RETURN_VALUE opcode is inserted. */ + unsigned b_return : 1; + /* depth of stack upon entry of block, computed by stackdepth() */ + int b_startdepth; + /* instruction offset for block, computed by assemble_jump_offsets() */ + int b_offset; } basicblock; /* fblockinfo tracks the current frame block. @@ -88,64 +88,64 @@ compiler IR. enum fblocktype { LOOP, EXCEPT, FINALLY_TRY, FINALLY_END }; struct fblockinfo { - enum fblocktype fb_type; - basicblock *fb_block; + enum fblocktype fb_type; + basicblock *fb_block; }; /* The following items change on entry and exit of code blocks. They must be saved and restored when returning to a block. */ struct compiler_unit { - PySTEntryObject *u_ste; - - PyObject *u_name; - /* The following fields are dicts that map objects to - the index of them in co_XXX. The index is used as - the argument for opcodes that refer to those collections. - */ - PyObject *u_consts; /* all constants */ - PyObject *u_names; /* all names */ - PyObject *u_varnames; /* local variables */ - PyObject *u_cellvars; /* cell variables */ - PyObject *u_freevars; /* free variables */ - - PyObject *u_private; /* for private name mangling */ - - int u_argcount; /* number of arguments for block */ - int u_kwonlyargcount; /* number of keyword only arguments for block */ - /* Pointer to the most recently allocated block. By following b_list - members, you can reach all early allocated blocks. */ - basicblock *u_blocks; - basicblock *u_curblock; /* pointer to current block */ - - int u_nfblocks; - struct fblockinfo u_fblock[CO_MAXBLOCKS]; - - int u_firstlineno; /* the first lineno of the block */ - int u_lineno; /* the lineno for the current stmt */ - int u_lineno_set; /* boolean to indicate whether instr - has been generated with current lineno */ + PySTEntryObject *u_ste; + + PyObject *u_name; + /* The following fields are dicts that map objects to + the index of them in co_XXX. The index is used as + the argument for opcodes that refer to those collections. + */ + PyObject *u_consts; /* all constants */ + PyObject *u_names; /* all names */ + PyObject *u_varnames; /* local variables */ + PyObject *u_cellvars; /* cell variables */ + PyObject *u_freevars; /* free variables */ + + PyObject *u_private; /* for private name mangling */ + + int u_argcount; /* number of arguments for block */ + int u_kwonlyargcount; /* number of keyword only arguments for block */ + /* Pointer to the most recently allocated block. By following b_list + members, you can reach all early allocated blocks. */ + basicblock *u_blocks; + basicblock *u_curblock; /* pointer to current block */ + + int u_nfblocks; + struct fblockinfo u_fblock[CO_MAXBLOCKS]; + + int u_firstlineno; /* the first lineno of the block */ + int u_lineno; /* the lineno for the current stmt */ + int u_lineno_set; /* boolean to indicate whether instr + has been generated with current lineno */ }; -/* This struct captures the global state of a compilation. +/* This struct captures the global state of a compilation. The u pointer points to the current compilation unit, while units -for enclosing blocks are stored in c_stack. The u and c_stack are +for enclosing blocks are stored in c_stack. The u and c_stack are managed by compiler_enter_scope() and compiler_exit_scope(). */ struct compiler { - const char *c_filename; - struct symtable *c_st; - PyFutureFeatures *c_future; /* pointer to module's __future__ */ - PyCompilerFlags *c_flags; + const char *c_filename; + struct symtable *c_st; + PyFutureFeatures *c_future; /* pointer to module's __future__ */ + PyCompilerFlags *c_flags; - int c_interactive; /* true if in interactive mode */ - int c_nestlevel; + int c_interactive; /* true if in interactive mode */ + int c_nestlevel; - struct compiler_unit *u; /* compiler state for current block */ - PyObject *c_stack; /* Python list holding compiler_unit ptrs */ - PyArena *c_arena; /* pointer to memory allocation arena */ + struct compiler_unit *u; /* compiler state for current block */ + PyObject *c_stack; /* Python list holding compiler_unit ptrs */ + PyArena *c_arena; /* pointer to memory allocation arena */ }; static int compiler_enter_scope(struct compiler *, identifier, void *, int); @@ -166,12 +166,12 @@ static int compiler_visit_keyword(struct compiler *, keyword_ty); static int compiler_visit_expr(struct compiler *, expr_ty); static int compiler_augassign(struct compiler *, stmt_ty); static int compiler_visit_slice(struct compiler *, slice_ty, - expr_context_ty); + expr_context_ty); static int compiler_push_fblock(struct compiler *, enum fblocktype, - basicblock *); + basicblock *); static void compiler_pop_fblock(struct compiler *, enum fblocktype, - basicblock *); + basicblock *); /* Returns true if there is a loop on the fblock stack. */ static int compiler_in_loop(struct compiler *); @@ -180,10 +180,10 @@ static int expr_constant(expr_ty e); static int compiler_with(struct compiler *, stmt_ty); static int compiler_call_helper(struct compiler *c, int n, - asdl_seq *args, - asdl_seq *keywords, - expr_ty starargs, - expr_ty kwargs); + asdl_seq *args, + asdl_seq *keywords, + expr_ty starargs, + expr_ty kwargs); static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__; @@ -193,172 +193,172 @@ static PyObject *__doc__; PyObject * _Py_Mangle(PyObject *privateobj, PyObject *ident) { - /* Name mangling: __private becomes _classname__private. - This is independent from how the name is used. */ - const Py_UNICODE *p, *name = PyUnicode_AS_UNICODE(ident); - Py_UNICODE *buffer; - size_t nlen, plen; - if (privateobj == NULL || !PyUnicode_Check(privateobj) || - name == NULL || name[0] != '_' || name[1] != '_') { - Py_INCREF(ident); - return ident; - } - p = PyUnicode_AS_UNICODE(privateobj); - nlen = Py_UNICODE_strlen(name); - /* Don't mangle __id__ or names with dots. - - The only time a name with a dot can occur is when - we are compiling an import statement that has a - package name. - - TODO(jhylton): Decide whether we want to support - mangling of the module name, e.g. __M.X. - */ - if ((name[nlen-1] == '_' && name[nlen-2] == '_') - || Py_UNICODE_strchr(name, '.')) { - Py_INCREF(ident); - return ident; /* Don't mangle __whatever__ */ - } - /* Strip leading underscores from class name */ - while (*p == '_') - p++; - if (*p == 0) { - Py_INCREF(ident); - return ident; /* Don't mangle if class is just underscores */ - } - plen = Py_UNICODE_strlen(p); - - assert(1 <= PY_SSIZE_T_MAX - nlen); - assert(1 + nlen <= PY_SSIZE_T_MAX - plen); - - ident = PyUnicode_FromStringAndSize(NULL, 1 + nlen + plen); - if (!ident) - return 0; - /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ - buffer = PyUnicode_AS_UNICODE(ident); - buffer[0] = '_'; - Py_UNICODE_strncpy(buffer+1, p, plen); - Py_UNICODE_strcpy(buffer+1+plen, name); - return ident; + /* Name mangling: __private becomes _classname__private. + This is independent from how the name is used. */ + const Py_UNICODE *p, *name = PyUnicode_AS_UNICODE(ident); + Py_UNICODE *buffer; + size_t nlen, plen; + if (privateobj == NULL || !PyUnicode_Check(privateobj) || + name == NULL || name[0] != '_' || name[1] != '_') { + Py_INCREF(ident); + return ident; + } + p = PyUnicode_AS_UNICODE(privateobj); + nlen = Py_UNICODE_strlen(name); + /* Don't mangle __id__ or names with dots. + + The only time a name with a dot can occur is when + we are compiling an import statement that has a + package name. + + TODO(jhylton): Decide whether we want to support + mangling of the module name, e.g. __M.X. + */ + if ((name[nlen-1] == '_' && name[nlen-2] == '_') + || Py_UNICODE_strchr(name, '.')) { + Py_INCREF(ident); + return ident; /* Don't mangle __whatever__ */ + } + /* Strip leading underscores from class name */ + while (*p == '_') + p++; + if (*p == 0) { + Py_INCREF(ident); + return ident; /* Don't mangle if class is just underscores */ + } + plen = Py_UNICODE_strlen(p); + + assert(1 <= PY_SSIZE_T_MAX - nlen); + assert(1 + nlen <= PY_SSIZE_T_MAX - plen); + + ident = PyUnicode_FromStringAndSize(NULL, 1 + nlen + plen); + if (!ident) + return 0; + /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ + buffer = PyUnicode_AS_UNICODE(ident); + buffer[0] = '_'; + Py_UNICODE_strncpy(buffer+1, p, plen); + Py_UNICODE_strcpy(buffer+1+plen, name); + return ident; } static int compiler_init(struct compiler *c) { - memset(c, 0, sizeof(struct compiler)); + memset(c, 0, sizeof(struct compiler)); - c->c_stack = PyList_New(0); - if (!c->c_stack) - return 0; + c->c_stack = PyList_New(0); + if (!c->c_stack) + return 0; - return 1; + return 1; } PyCodeObject * PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, - PyArena *arena) -{ - struct compiler c; - PyCodeObject *co = NULL; - PyCompilerFlags local_flags; - int merged; - - if (!__doc__) { - __doc__ = PyUnicode_InternFromString("__doc__"); - if (!__doc__) - return NULL; - } - - if (!compiler_init(&c)) - return NULL; - c.c_filename = filename; - c.c_arena = arena; - c.c_future = PyFuture_FromAST(mod, filename); - if (c.c_future == NULL) - goto finally; - if (!flags) { - local_flags.cf_flags = 0; - flags = &local_flags; - } - merged = c.c_future->ff_features | flags->cf_flags; - c.c_future->ff_features = merged; - flags->cf_flags = merged; - c.c_flags = flags; - c.c_nestlevel = 0; - - c.c_st = PySymtable_Build(mod, filename, c.c_future); - if (c.c_st == NULL) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_SystemError, "no symtable"); - goto finally; - } - - co = compiler_mod(&c, mod); + PyArena *arena) +{ + struct compiler c; + PyCodeObject *co = NULL; + PyCompilerFlags local_flags; + int merged; + + if (!__doc__) { + __doc__ = PyUnicode_InternFromString("__doc__"); + if (!__doc__) + return NULL; + } + + if (!compiler_init(&c)) + return NULL; + c.c_filename = filename; + c.c_arena = arena; + c.c_future = PyFuture_FromAST(mod, filename); + if (c.c_future == NULL) + goto finally; + if (!flags) { + local_flags.cf_flags = 0; + flags = &local_flags; + } + merged = c.c_future->ff_features | flags->cf_flags; + c.c_future->ff_features = merged; + flags->cf_flags = merged; + c.c_flags = flags; + c.c_nestlevel = 0; + + c.c_st = PySymtable_Build(mod, filename, c.c_future); + if (c.c_st == NULL) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_SystemError, "no symtable"); + goto finally; + } + + co = compiler_mod(&c, mod); finally: - compiler_free(&c); - assert(co || PyErr_Occurred()); - return co; + compiler_free(&c); + assert(co || PyErr_Occurred()); + return co; } PyCodeObject * PyNode_Compile(struct _node *n, const char *filename) { - PyCodeObject *co = NULL; - mod_ty mod; - PyArena *arena = PyArena_New(); - if (!arena) - return NULL; - mod = PyAST_FromNode(n, NULL, filename, arena); - if (mod) - co = PyAST_Compile(mod, filename, NULL, arena); - PyArena_Free(arena); - return co; + PyCodeObject *co = NULL; + mod_ty mod; + PyArena *arena = PyArena_New(); + if (!arena) + return NULL; + mod = PyAST_FromNode(n, NULL, filename, arena); + if (mod) + co = PyAST_Compile(mod, filename, NULL, arena); + PyArena_Free(arena); + return co; } static void compiler_free(struct compiler *c) { - if (c->c_st) - PySymtable_Free(c->c_st); - if (c->c_future) - PyObject_Free(c->c_future); - Py_DECREF(c->c_stack); + if (c->c_st) + PySymtable_Free(c->c_st); + if (c->c_future) + PyObject_Free(c->c_future); + Py_DECREF(c->c_stack); } static PyObject * list2dict(PyObject *list) { - Py_ssize_t i, n; - PyObject *v, *k; - PyObject *dict = PyDict_New(); - if (!dict) return NULL; - - n = PyList_Size(list); - for (i = 0; i < n; i++) { - v = PyLong_FromLong(i); - if (!v) { - Py_DECREF(dict); - return NULL; - } - k = PyList_GET_ITEM(list, i); - k = PyTuple_Pack(2, k, k->ob_type); - if (k == NULL || PyDict_SetItem(dict, k, v) < 0) { - Py_XDECREF(k); - Py_DECREF(v); - Py_DECREF(dict); - return NULL; - } - Py_DECREF(k); - Py_DECREF(v); - } - return dict; + Py_ssize_t i, n; + PyObject *v, *k; + PyObject *dict = PyDict_New(); + if (!dict) return NULL; + + n = PyList_Size(list); + for (i = 0; i < n; i++) { + v = PyLong_FromLong(i); + if (!v) { + Py_DECREF(dict); + return NULL; + } + k = PyList_GET_ITEM(list, i); + k = PyTuple_Pack(2, k, k->ob_type); + if (k == NULL || PyDict_SetItem(dict, k, v) < 0) { + Py_XDECREF(k); + Py_DECREF(v); + Py_DECREF(dict); + return NULL; + } + Py_DECREF(k); + Py_DECREF(v); + } + return dict; } /* Return new dict containing names from src that match scope(s). src is a symbol table dictionary. If the scope of a name matches -either scope_type or flag is set, insert it into the new dict. The +either scope_type or flag is set, insert it into the new dict. The values are integers, starting at offset and increasing by one for each key. */ @@ -366,182 +366,182 @@ each key. static PyObject * dictbytype(PyObject *src, int scope_type, int flag, int offset) { - Py_ssize_t pos = 0, i = offset, scope; - PyObject *k, *v, *dest = PyDict_New(); - - assert(offset >= 0); - if (dest == NULL) - return NULL; - - while (PyDict_Next(src, &pos, &k, &v)) { - /* XXX this should probably be a macro in symtable.h */ - long vi; - assert(PyLong_Check(v)); - vi = PyLong_AS_LONG(v); - scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK; - - if (scope == scope_type || vi & flag) { - PyObject *tuple, *item = PyLong_FromLong(i); - if (item == NULL) { - Py_DECREF(dest); - return NULL; - } - i++; - tuple = PyTuple_Pack(2, k, k->ob_type); - if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) { - Py_DECREF(item); - Py_DECREF(dest); - Py_XDECREF(tuple); - return NULL; - } - Py_DECREF(item); - Py_DECREF(tuple); - } - } - return dest; + Py_ssize_t pos = 0, i = offset, scope; + PyObject *k, *v, *dest = PyDict_New(); + + assert(offset >= 0); + if (dest == NULL) + return NULL; + + while (PyDict_Next(src, &pos, &k, &v)) { + /* XXX this should probably be a macro in symtable.h */ + long vi; + assert(PyLong_Check(v)); + vi = PyLong_AS_LONG(v); + scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK; + + if (scope == scope_type || vi & flag) { + PyObject *tuple, *item = PyLong_FromLong(i); + if (item == NULL) { + Py_DECREF(dest); + return NULL; + } + i++; + tuple = PyTuple_Pack(2, k, k->ob_type); + if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) { + Py_DECREF(item); + Py_DECREF(dest); + Py_XDECREF(tuple); + return NULL; + } + Py_DECREF(item); + Py_DECREF(tuple); + } + } + return dest; } static void compiler_unit_check(struct compiler_unit *u) { - basicblock *block; - for (block = u->u_blocks; block != NULL; block = block->b_list) { - assert((void *)block != (void *)0xcbcbcbcb); - assert((void *)block != (void *)0xfbfbfbfb); - assert((void *)block != (void *)0xdbdbdbdb); - if (block->b_instr != NULL) { - assert(block->b_ialloc > 0); - assert(block->b_iused > 0); - assert(block->b_ialloc >= block->b_iused); - } - else { - assert (block->b_iused == 0); - assert (block->b_ialloc == 0); - } - } + basicblock *block; + for (block = u->u_blocks; block != NULL; block = block->b_list) { + assert((void *)block != (void *)0xcbcbcbcb); + assert((void *)block != (void *)0xfbfbfbfb); + assert((void *)block != (void *)0xdbdbdbdb); + if (block->b_instr != NULL) { + assert(block->b_ialloc > 0); + assert(block->b_iused > 0); + assert(block->b_ialloc >= block->b_iused); + } + else { + assert (block->b_iused == 0); + assert (block->b_ialloc == 0); + } + } } static void compiler_unit_free(struct compiler_unit *u) { - basicblock *b, *next; - - compiler_unit_check(u); - b = u->u_blocks; - while (b != NULL) { - if (b->b_instr) - PyObject_Free((void *)b->b_instr); - next = b->b_list; - PyObject_Free((void *)b); - b = next; - } - Py_CLEAR(u->u_ste); - Py_CLEAR(u->u_name); - Py_CLEAR(u->u_consts); - Py_CLEAR(u->u_names); - Py_CLEAR(u->u_varnames); - Py_CLEAR(u->u_freevars); - Py_CLEAR(u->u_cellvars); - Py_CLEAR(u->u_private); - PyObject_Free(u); + basicblock *b, *next; + + compiler_unit_check(u); + b = u->u_blocks; + while (b != NULL) { + if (b->b_instr) + PyObject_Free((void *)b->b_instr); + next = b->b_list; + PyObject_Free((void *)b); + b = next; + } + Py_CLEAR(u->u_ste); + Py_CLEAR(u->u_name); + Py_CLEAR(u->u_consts); + Py_CLEAR(u->u_names); + Py_CLEAR(u->u_varnames); + Py_CLEAR(u->u_freevars); + Py_CLEAR(u->u_cellvars); + Py_CLEAR(u->u_private); + PyObject_Free(u); } static int compiler_enter_scope(struct compiler *c, identifier name, void *key, - int lineno) -{ - struct compiler_unit *u; - - u = (struct compiler_unit *)PyObject_Malloc(sizeof( - struct compiler_unit)); - if (!u) { - PyErr_NoMemory(); - return 0; - } - memset(u, 0, sizeof(struct compiler_unit)); - u->u_argcount = 0; - u->u_kwonlyargcount = 0; - u->u_ste = PySymtable_Lookup(c->c_st, key); - if (!u->u_ste) { - compiler_unit_free(u); - return 0; - } - Py_INCREF(name); - u->u_name = name; - u->u_varnames = list2dict(u->u_ste->ste_varnames); - u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0); - if (!u->u_varnames || !u->u_cellvars) { - compiler_unit_free(u); - return 0; - } - - u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, - PyDict_Size(u->u_cellvars)); - if (!u->u_freevars) { - compiler_unit_free(u); - return 0; - } - - u->u_blocks = NULL; - u->u_nfblocks = 0; - u->u_firstlineno = lineno; - u->u_lineno = 0; - u->u_lineno_set = 0; - u->u_consts = PyDict_New(); - if (!u->u_consts) { - compiler_unit_free(u); - return 0; - } - u->u_names = PyDict_New(); - if (!u->u_names) { - compiler_unit_free(u); - return 0; - } - - u->u_private = NULL; - - /* Push the old compiler_unit on the stack. */ - if (c->u) { - PyObject *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL); - if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { - Py_XDECREF(capsule); - compiler_unit_free(u); - return 0; - } - Py_DECREF(capsule); - u->u_private = c->u->u_private; - Py_XINCREF(u->u_private); - } - c->u = u; - - c->c_nestlevel++; - if (compiler_use_new_block(c) == NULL) - return 0; - - return 1; + int lineno) +{ + struct compiler_unit *u; + + u = (struct compiler_unit *)PyObject_Malloc(sizeof( + struct compiler_unit)); + if (!u) { + PyErr_NoMemory(); + return 0; + } + memset(u, 0, sizeof(struct compiler_unit)); + u->u_argcount = 0; + u->u_kwonlyargcount = 0; + u->u_ste = PySymtable_Lookup(c->c_st, key); + if (!u->u_ste) { + compiler_unit_free(u); + return 0; + } + Py_INCREF(name); + u->u_name = name; + u->u_varnames = list2dict(u->u_ste->ste_varnames); + u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0); + if (!u->u_varnames || !u->u_cellvars) { + compiler_unit_free(u); + return 0; + } + + u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, + PyDict_Size(u->u_cellvars)); + if (!u->u_freevars) { + compiler_unit_free(u); + return 0; + } + + u->u_blocks = NULL; + u->u_nfblocks = 0; + u->u_firstlineno = lineno; + u->u_lineno = 0; + u->u_lineno_set = 0; + u->u_consts = PyDict_New(); + if (!u->u_consts) { + compiler_unit_free(u); + return 0; + } + u->u_names = PyDict_New(); + if (!u->u_names) { + compiler_unit_free(u); + return 0; + } + + u->u_private = NULL; + + /* Push the old compiler_unit on the stack. */ + if (c->u) { + PyObject *capsule = PyCapsule_New(c->u, COMPILER_CAPSULE_NAME_COMPILER_UNIT, NULL); + if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { + Py_XDECREF(capsule); + compiler_unit_free(u); + return 0; + } + Py_DECREF(capsule); + u->u_private = c->u->u_private; + Py_XINCREF(u->u_private); + } + c->u = u; + + c->c_nestlevel++; + if (compiler_use_new_block(c) == NULL) + return 0; + + return 1; } static void compiler_exit_scope(struct compiler *c) { - int n; - PyObject *capsule; - - c->c_nestlevel--; - compiler_unit_free(c->u); - /* Restore c->u to the parent unit. */ - n = PyList_GET_SIZE(c->c_stack) - 1; - if (n >= 0) { - capsule = PyList_GET_ITEM(c->c_stack, n); - c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); - assert(c->u); - /* we are deleting from a list so this really shouldn't fail */ - if (PySequence_DelItem(c->c_stack, n) < 0) - Py_FatalError("compiler_exit_scope()"); - compiler_unit_check(c->u); - } - else - c->u = NULL; + int n; + PyObject *capsule; + + c->c_nestlevel--; + compiler_unit_free(c->u); + /* Restore c->u to the parent unit. */ + n = PyList_GET_SIZE(c->c_stack) - 1; + if (n >= 0) { + capsule = PyList_GET_ITEM(c->c_stack, n); + c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + assert(c->u); + /* we are deleting from a list so this really shouldn't fail */ + if (PySequence_DelItem(c->c_stack, n) < 0) + Py_FatalError("compiler_exit_scope()"); + compiler_unit_check(c->u); + } + else + c->u = NULL; } @@ -552,50 +552,50 @@ compiler_exit_scope(struct compiler *c) static basicblock * compiler_new_block(struct compiler *c) { - basicblock *b; - struct compiler_unit *u; + basicblock *b; + struct compiler_unit *u; - u = c->u; - b = (basicblock *)PyObject_Malloc(sizeof(basicblock)); - if (b == NULL) { - PyErr_NoMemory(); - return NULL; - } - memset((void *)b, 0, sizeof(basicblock)); - /* Extend the singly linked list of blocks with new block. */ - b->b_list = u->u_blocks; - u->u_blocks = b; - return b; + u = c->u; + b = (basicblock *)PyObject_Malloc(sizeof(basicblock)); + if (b == NULL) { + PyErr_NoMemory(); + return NULL; + } + memset((void *)b, 0, sizeof(basicblock)); + /* Extend the singly linked list of blocks with new block. */ + b->b_list = u->u_blocks; + u->u_blocks = b; + return b; } 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; + 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); - if (block == NULL) - return NULL; - c->u->u_curblock->b_next = block; - c->u->u_curblock = block; - return block; + basicblock *block = compiler_new_block(c); + if (block == NULL) + return NULL; + c->u->u_curblock->b_next = block; + c->u->u_curblock = block; + return block; } static basicblock * compiler_use_next_block(struct compiler *c, basicblock *block) { - assert(block != NULL); - c->u->u_curblock->b_next = block; - c->u->u_curblock = block; - return block; + assert(block != NULL); + c->u->u_curblock->b_next = block; + c->u->u_curblock = block; + return block; } /* Returns the offset of the next instruction in the current block's @@ -606,44 +606,44 @@ compiler_use_next_block(struct compiler *c, basicblock *block) static int compiler_next_instr(struct compiler *c, basicblock *b) { - assert(b != NULL); - if (b->b_instr == NULL) { - b->b_instr = (struct instr *)PyObject_Malloc( - sizeof(struct instr) * DEFAULT_BLOCK_SIZE); - if (b->b_instr == NULL) { - PyErr_NoMemory(); - return -1; - } - b->b_ialloc = DEFAULT_BLOCK_SIZE; - memset((char *)b->b_instr, 0, - sizeof(struct instr) * DEFAULT_BLOCK_SIZE); - } - else if (b->b_iused == b->b_ialloc) { - struct instr *tmp; - size_t oldsize, newsize; - oldsize = b->b_ialloc * sizeof(struct instr); - newsize = oldsize << 1; - - if (oldsize > (PY_SIZE_MAX >> 1)) { - PyErr_NoMemory(); - return -1; - } - - if (newsize == 0) { - PyErr_NoMemory(); - return -1; - } - b->b_ialloc <<= 1; - tmp = (struct instr *)PyObject_Realloc( - (void *)b->b_instr, newsize); - if (tmp == NULL) { - PyErr_NoMemory(); - return -1; - } - b->b_instr = tmp; - memset((char *)b->b_instr + oldsize, 0, newsize - oldsize); - } - return b->b_iused++; + assert(b != NULL); + if (b->b_instr == NULL) { + b->b_instr = (struct instr *)PyObject_Malloc( + sizeof(struct instr) * DEFAULT_BLOCK_SIZE); + if (b->b_instr == NULL) { + PyErr_NoMemory(); + return -1; + } + b->b_ialloc = DEFAULT_BLOCK_SIZE; + memset((char *)b->b_instr, 0, + sizeof(struct instr) * DEFAULT_BLOCK_SIZE); + } + else if (b->b_iused == b->b_ialloc) { + struct instr *tmp; + size_t oldsize, newsize; + oldsize = b->b_ialloc * sizeof(struct instr); + newsize = oldsize << 1; + + if (oldsize > (PY_SIZE_MAX >> 1)) { + PyErr_NoMemory(); + return -1; + } + + if (newsize == 0) { + PyErr_NoMemory(); + return -1; + } + b->b_ialloc <<= 1; + tmp = (struct instr *)PyObject_Realloc( + (void *)b->b_instr, newsize); + if (tmp == NULL) { + PyErr_NoMemory(); + return -1; + } + b->b_instr = tmp; + memset((char *)b->b_instr + oldsize, 0, newsize - oldsize); + } + return b->b_iused++; } /* Set the i_lineno member of the instruction at offset off if the @@ -661,210 +661,210 @@ compiler_next_instr(struct compiler *c, basicblock *b) static void compiler_set_lineno(struct compiler *c, int off) { - basicblock *b; - if (c->u->u_lineno_set) - return; - c->u->u_lineno_set = 1; - b = c->u->u_curblock; - b->b_instr[off].i_lineno = c->u->u_lineno; + basicblock *b; + if (c->u->u_lineno_set) + return; + c->u->u_lineno_set = 1; + b = c->u->u_curblock; + b->b_instr[off].i_lineno = c->u->u_lineno; } static int opcode_stack_effect(int opcode, int oparg) { - switch (opcode) { - case POP_TOP: - return -1; - case ROT_TWO: - case ROT_THREE: - return 0; - case DUP_TOP: - return 1; - case ROT_FOUR: - return 0; - - case UNARY_POSITIVE: - case UNARY_NEGATIVE: - case UNARY_NOT: - case UNARY_INVERT: - return 0; - - case SET_ADD: - case LIST_APPEND: - return -1; - case MAP_ADD: - return -2; - - case BINARY_POWER: - case BINARY_MULTIPLY: - case BINARY_MODULO: - case BINARY_ADD: - case BINARY_SUBTRACT: - case BINARY_SUBSCR: - case BINARY_FLOOR_DIVIDE: - case BINARY_TRUE_DIVIDE: - return -1; - case INPLACE_FLOOR_DIVIDE: - case INPLACE_TRUE_DIVIDE: - return -1; - - case INPLACE_ADD: - case INPLACE_SUBTRACT: - case INPLACE_MULTIPLY: - case INPLACE_MODULO: - return -1; - case STORE_SUBSCR: - return -3; - case STORE_MAP: - return -2; - case DELETE_SUBSCR: - return -2; - - case BINARY_LSHIFT: - case BINARY_RSHIFT: - case BINARY_AND: - case BINARY_XOR: - case BINARY_OR: - return -1; - case INPLACE_POWER: - return -1; - case GET_ITER: - return 0; - - case PRINT_EXPR: - return -1; - case LOAD_BUILD_CLASS: - return 1; - case INPLACE_LSHIFT: - case INPLACE_RSHIFT: - case INPLACE_AND: - case INPLACE_XOR: - case INPLACE_OR: - return -1; - case BREAK_LOOP: - return 0; - case SETUP_WITH: - return 7; - case WITH_CLEANUP: - return -1; /* XXX Sometimes more */ - case STORE_LOCALS: - return -1; - case RETURN_VALUE: - return -1; - case IMPORT_STAR: - return -1; - case YIELD_VALUE: - return 0; - - case POP_BLOCK: - return 0; - case POP_EXCEPT: - return 0; /* -3 except if bad bytecode */ - case END_FINALLY: - return -1; /* or -2 or -3 if exception occurred */ - - case STORE_NAME: - return -1; - case DELETE_NAME: - return 0; - case UNPACK_SEQUENCE: - return oparg-1; - case UNPACK_EX: - return (oparg&0xFF) + (oparg>>8); - case FOR_ITER: - return 1; /* or -1, at end of iterator */ - - case STORE_ATTR: - return -2; - case DELETE_ATTR: - return -1; - case STORE_GLOBAL: - return -1; - case DELETE_GLOBAL: - return 0; - case DUP_TOPX: - return oparg; - case LOAD_CONST: - return 1; - case LOAD_NAME: - return 1; - case BUILD_TUPLE: - case BUILD_LIST: - case BUILD_SET: - return 1-oparg; - case BUILD_MAP: - return 1; - case LOAD_ATTR: - return 0; - case COMPARE_OP: - return -1; - case IMPORT_NAME: - return -1; - case IMPORT_FROM: - return 1; - - case JUMP_FORWARD: - case JUMP_IF_TRUE_OR_POP: /* -1 if jump not taken */ - case JUMP_IF_FALSE_OR_POP: /* "" */ - case JUMP_ABSOLUTE: - return 0; - - case POP_JUMP_IF_FALSE: - case POP_JUMP_IF_TRUE: - return -1; - - case LOAD_GLOBAL: - return 1; - - case CONTINUE_LOOP: - return 0; - case SETUP_LOOP: - return 0; - case SETUP_EXCEPT: - case SETUP_FINALLY: - return 6; /* can push 3 values for the new exception - + 3 others for the previous exception state */ - - case LOAD_FAST: - return 1; - case STORE_FAST: - return -1; - case DELETE_FAST: - return 0; - - case RAISE_VARARGS: - return -oparg; + switch (opcode) { + case POP_TOP: + return -1; + case ROT_TWO: + case ROT_THREE: + return 0; + case DUP_TOP: + return 1; + case ROT_FOUR: + return 0; + + case UNARY_POSITIVE: + case UNARY_NEGATIVE: + case UNARY_NOT: + case UNARY_INVERT: + return 0; + + case SET_ADD: + case LIST_APPEND: + return -1; + case MAP_ADD: + return -2; + + case BINARY_POWER: + case BINARY_MULTIPLY: + case BINARY_MODULO: + case BINARY_ADD: + case BINARY_SUBTRACT: + case BINARY_SUBSCR: + case BINARY_FLOOR_DIVIDE: + case BINARY_TRUE_DIVIDE: + return -1; + case INPLACE_FLOOR_DIVIDE: + case INPLACE_TRUE_DIVIDE: + return -1; + + case INPLACE_ADD: + case INPLACE_SUBTRACT: + case INPLACE_MULTIPLY: + case INPLACE_MODULO: + return -1; + case STORE_SUBSCR: + return -3; + case STORE_MAP: + return -2; + case DELETE_SUBSCR: + return -2; + + case BINARY_LSHIFT: + case BINARY_RSHIFT: + case BINARY_AND: + case BINARY_XOR: + case BINARY_OR: + return -1; + case INPLACE_POWER: + return -1; + case GET_ITER: + return 0; + + case PRINT_EXPR: + return -1; + case LOAD_BUILD_CLASS: + return 1; + case INPLACE_LSHIFT: + case INPLACE_RSHIFT: + case INPLACE_AND: + case INPLACE_XOR: + case INPLACE_OR: + return -1; + case BREAK_LOOP: + return 0; + case SETUP_WITH: + return 7; + case WITH_CLEANUP: + return -1; /* XXX Sometimes more */ + case STORE_LOCALS: + return -1; + case RETURN_VALUE: + return -1; + case IMPORT_STAR: + return -1; + case YIELD_VALUE: + return 0; + + case POP_BLOCK: + return 0; + case POP_EXCEPT: + return 0; /* -3 except if bad bytecode */ + case END_FINALLY: + return -1; /* or -2 or -3 if exception occurred */ + + case STORE_NAME: + return -1; + case DELETE_NAME: + return 0; + case UNPACK_SEQUENCE: + return oparg-1; + case UNPACK_EX: + return (oparg&0xFF) + (oparg>>8); + case FOR_ITER: + return 1; /* or -1, at end of iterator */ + + case STORE_ATTR: + return -2; + case DELETE_ATTR: + return -1; + case STORE_GLOBAL: + return -1; + case DELETE_GLOBAL: + return 0; + case DUP_TOPX: + return oparg; + case LOAD_CONST: + return 1; + case LOAD_NAME: + return 1; + case BUILD_TUPLE: + case BUILD_LIST: + case BUILD_SET: + return 1-oparg; + case BUILD_MAP: + return 1; + case LOAD_ATTR: + return 0; + case COMPARE_OP: + return -1; + case IMPORT_NAME: + return -1; + case IMPORT_FROM: + return 1; + + case JUMP_FORWARD: + case JUMP_IF_TRUE_OR_POP: /* -1 if jump not taken */ + case JUMP_IF_FALSE_OR_POP: /* "" */ + case JUMP_ABSOLUTE: + return 0; + + case POP_JUMP_IF_FALSE: + case POP_JUMP_IF_TRUE: + return -1; + + case LOAD_GLOBAL: + return 1; + + case CONTINUE_LOOP: + return 0; + case SETUP_LOOP: + return 0; + case SETUP_EXCEPT: + case SETUP_FINALLY: + return 6; /* can push 3 values for the new exception + + 3 others for the previous exception state */ + + case LOAD_FAST: + return 1; + case STORE_FAST: + return -1; + case DELETE_FAST: + return 0; + + case RAISE_VARARGS: + return -oparg; #define NARGS(o) (((o) % 256) + 2*(((o) / 256) % 256)) - case CALL_FUNCTION: - return -NARGS(oparg); - case CALL_FUNCTION_VAR: - case CALL_FUNCTION_KW: - return -NARGS(oparg)-1; - case CALL_FUNCTION_VAR_KW: - return -NARGS(oparg)-2; - case MAKE_FUNCTION: - return -NARGS(oparg) - ((oparg >> 16) & 0xffff); - case MAKE_CLOSURE: - return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff); + case CALL_FUNCTION: + return -NARGS(oparg); + case CALL_FUNCTION_VAR: + case CALL_FUNCTION_KW: + return -NARGS(oparg)-1; + case CALL_FUNCTION_VAR_KW: + return -NARGS(oparg)-2; + case MAKE_FUNCTION: + return -NARGS(oparg) - ((oparg >> 16) & 0xffff); + case MAKE_CLOSURE: + return -1 - NARGS(oparg) - ((oparg >> 16) & 0xffff); #undef NARGS - case BUILD_SLICE: - if (oparg == 3) - return -2; - else - return -1; - - case LOAD_CLOSURE: - return 1; - case LOAD_DEREF: - return 1; - case STORE_DEREF: - return -1; - default: - fprintf(stderr, "opcode = %d\n", opcode); - Py_FatalError("opcode_stack_effect()"); - - } - return 0; /* not reachable */ + case BUILD_SLICE: + if (oparg == 3) + return -2; + else + return -1; + + case LOAD_CLOSURE: + return 1; + case LOAD_DEREF: + return 1; + case STORE_DEREF: + return -1; + default: + fprintf(stderr, "opcode = %d\n", opcode); + Py_FatalError("opcode_stack_effect()"); + + } + return 0; /* not reachable */ } /* Add an opcode with no argument. @@ -874,116 +874,116 @@ opcode_stack_effect(int opcode, int oparg) static int compiler_addop(struct compiler *c, int opcode) { - basicblock *b; - struct instr *i; - int off; - off = compiler_next_instr(c, c->u->u_curblock); - if (off < 0) - return 0; - b = c->u->u_curblock; - i = &b->b_instr[off]; - i->i_opcode = opcode; - i->i_hasarg = 0; - if (opcode == RETURN_VALUE) - b->b_return = 1; - compiler_set_lineno(c, off); - return 1; + basicblock *b; + struct instr *i; + int off; + off = compiler_next_instr(c, c->u->u_curblock); + if (off < 0) + return 0; + b = c->u->u_curblock; + i = &b->b_instr[off]; + i->i_opcode = opcode; + i->i_hasarg = 0; + if (opcode == RETURN_VALUE) + b->b_return = 1; + compiler_set_lineno(c, off); + return 1; } static int compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) { - PyObject *t, *v; - Py_ssize_t arg; - double d; - - /* necessary to make sure types aren't coerced (e.g., int and long) */ - /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ - if (PyFloat_Check(o)) { - d = PyFloat_AS_DOUBLE(o); - /* all we need is to make the tuple different in either the 0.0 - * or -0.0 case from all others, just to avoid the "coercion". - */ - if (d == 0.0 && copysign(1.0, d) < 0.0) - t = PyTuple_Pack(3, o, o->ob_type, Py_None); - else - t = PyTuple_Pack(2, o, o->ob_type); - } - else if (PyComplex_Check(o)) { - Py_complex z; - int real_negzero, imag_negzero; - /* For the complex case we must make complex(x, 0.) - different from complex(x, -0.) and complex(0., y) - different from complex(-0., y), for any x and y. - All four complex zeros must be distinguished.*/ - z = PyComplex_AsCComplex(o); - real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; - imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; - if (real_negzero && imag_negzero) { - t = PyTuple_Pack(5, o, o->ob_type, - Py_None, Py_None, Py_None); - } - else if (imag_negzero) { - t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); - } - else if (real_negzero) { - t = PyTuple_Pack(3, o, o->ob_type, Py_None); - } - else { - t = PyTuple_Pack(2, o, o->ob_type); - } - } - else { - t = PyTuple_Pack(2, o, o->ob_type); - } - if (t == NULL) - return -1; - - v = PyDict_GetItem(dict, t); - if (!v) { - if (PyErr_Occurred()) - return -1; - arg = PyDict_Size(dict); - v = PyLong_FromLong(arg); - if (!v) { - Py_DECREF(t); - return -1; - } - if (PyDict_SetItem(dict, t, v) < 0) { - Py_DECREF(t); - Py_DECREF(v); - return -1; - } - Py_DECREF(v); - } - else - arg = PyLong_AsLong(v); - Py_DECREF(t); - return arg; + PyObject *t, *v; + Py_ssize_t arg; + double d; + + /* necessary to make sure types aren't coerced (e.g., int and long) */ + /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ + if (PyFloat_Check(o)) { + d = PyFloat_AS_DOUBLE(o); + /* all we need is to make the tuple different in either the 0.0 + * or -0.0 case from all others, just to avoid the "coercion". + */ + if (d == 0.0 && copysign(1.0, d) < 0.0) + t = PyTuple_Pack(3, o, o->ob_type, Py_None); + else + t = PyTuple_Pack(2, o, o->ob_type); + } + else if (PyComplex_Check(o)) { + Py_complex z; + int real_negzero, imag_negzero; + /* For the complex case we must make complex(x, 0.) + different from complex(x, -0.) and complex(0., y) + different from complex(-0., y), for any x and y. + All four complex zeros must be distinguished.*/ + z = PyComplex_AsCComplex(o); + real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; + imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; + if (real_negzero && imag_negzero) { + t = PyTuple_Pack(5, o, o->ob_type, + Py_None, Py_None, Py_None); + } + else if (imag_negzero) { + t = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); + } + else if (real_negzero) { + t = PyTuple_Pack(3, o, o->ob_type, Py_None); + } + else { + t = PyTuple_Pack(2, o, o->ob_type); + } + } + else { + t = PyTuple_Pack(2, o, o->ob_type); + } + if (t == NULL) + return -1; + + v = PyDict_GetItem(dict, t); + if (!v) { + if (PyErr_Occurred()) + return -1; + arg = PyDict_Size(dict); + v = PyLong_FromLong(arg); + if (!v) { + Py_DECREF(t); + return -1; + } + if (PyDict_SetItem(dict, t, v) < 0) { + Py_DECREF(t); + Py_DECREF(v); + return -1; + } + Py_DECREF(v); + } + else + arg = PyLong_AsLong(v); + Py_DECREF(t); + return arg; } static int compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, - PyObject *o) + PyObject *o) { int arg = compiler_add_o(c, dict, o); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } static int compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, - PyObject *o) + PyObject *o) { int arg; PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) - return 0; + return 0; arg = compiler_add_o(c, dict, mangled); Py_DECREF(mangled); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -994,43 +994,43 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, static int compiler_addop_i(struct compiler *c, int opcode, int oparg) { - struct instr *i; - int off; - off = compiler_next_instr(c, c->u->u_curblock); - if (off < 0) - return 0; - i = &c->u->u_curblock->b_instr[off]; - i->i_opcode = opcode; - i->i_oparg = oparg; - i->i_hasarg = 1; - compiler_set_lineno(c, off); - return 1; + struct instr *i; + int off; + off = compiler_next_instr(c, c->u->u_curblock); + if (off < 0) + return 0; + i = &c->u->u_curblock->b_instr[off]; + i->i_opcode = opcode; + i->i_oparg = oparg; + i->i_hasarg = 1; + compiler_set_lineno(c, off); + return 1; } static int compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) { - struct instr *i; - int off; - - assert(b != NULL); - off = compiler_next_instr(c, c->u->u_curblock); - if (off < 0) - return 0; - i = &c->u->u_curblock->b_instr[off]; - i->i_opcode = opcode; - i->i_target = b; - i->i_hasarg = 1; - if (absolute) - i->i_jabs = 1; - else - i->i_jrel = 1; - compiler_set_lineno(c, off); - 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 + struct instr *i; + int off; + + assert(b != NULL); + off = compiler_next_instr(c, c->u->u_curblock); + if (off < 0) + return 0; + i = &c->u->u_curblock->b_instr[off]; + i->i_opcode = opcode; + i->i_target = b; + i->i_hasarg = 1; + if (absolute) + i->i_jabs = 1; + else + i->i_jrel = 1; + compiler_set_lineno(c, off); + 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. */ @@ -1041,50 +1041,50 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) #define NEW_BLOCK(C) { \ - if (compiler_use_new_block((C)) == NULL) \ - return 0; \ + if (compiler_use_new_block((C)) == NULL) \ + return 0; \ } #define NEXT_BLOCK(C) { \ - if (compiler_next_block((C)) == NULL) \ - return 0; \ + if (compiler_next_block((C)) == NULL) \ + return 0; \ } #define ADDOP(C, OP) { \ - if (!compiler_addop((C), (OP))) \ - return 0; \ + if (!compiler_addop((C), (OP))) \ + return 0; \ } #define ADDOP_IN_SCOPE(C, OP) { \ - if (!compiler_addop((C), (OP))) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ + if (!compiler_addop((C), (OP))) { \ + compiler_exit_scope(c); \ + return 0; \ + } \ } #define ADDOP_O(C, OP, O, TYPE) { \ - if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \ - return 0; \ + if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \ + return 0; \ } #define ADDOP_NAME(C, OP, O, TYPE) { \ - if (!compiler_addop_name((C), (OP), (C)->u->u_ ## TYPE, (O))) \ - return 0; \ + if (!compiler_addop_name((C), (OP), (C)->u->u_ ## TYPE, (O))) \ + return 0; \ } #define ADDOP_I(C, OP, O) { \ - if (!compiler_addop_i((C), (OP), (O))) \ - return 0; \ + if (!compiler_addop_i((C), (OP), (O))) \ + return 0; \ } #define ADDOP_JABS(C, OP, O) { \ - if (!compiler_addop_j((C), (OP), (O), 1)) \ - return 0; \ + if (!compiler_addop_j((C), (OP), (O), 1)) \ + return 0; \ } #define ADDOP_JREL(C, OP, O) { \ - if (!compiler_addop_j((C), (OP), (O), 0)) \ - return 0; \ + if (!compiler_addop_j((C), (OP), (O), 0)) \ + return 0; \ } /* VISIT and VISIT_SEQ takes an ASDL type as their second argument. They use @@ -1092,49 +1092,49 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) */ #define VISIT(C, TYPE, V) {\ - if (!compiler_visit_ ## TYPE((C), (V))) \ - return 0; \ + if (!compiler_visit_ ## TYPE((C), (V))) \ + return 0; \ } #define VISIT_IN_SCOPE(C, TYPE, V) {\ - if (!compiler_visit_ ## TYPE((C), (V))) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ + if (!compiler_visit_ ## TYPE((C), (V))) { \ + compiler_exit_scope(c); \ + return 0; \ + } \ } #define VISIT_SLICE(C, V, CTX) {\ - if (!compiler_visit_slice((C), (V), (CTX))) \ - return 0; \ + if (!compiler_visit_slice((C), (V), (CTX))) \ + return 0; \ } #define VISIT_SEQ(C, TYPE, SEQ) { \ - int _i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \ - if (!compiler_visit_ ## TYPE((C), elt)) \ - return 0; \ - } \ + int _i; \ + asdl_seq *seq = (SEQ); /* avoid variable capture */ \ + for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \ + TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \ + if (!compiler_visit_ ## TYPE((C), elt)) \ + return 0; \ + } \ } #define VISIT_SEQ_IN_SCOPE(C, TYPE, SEQ) { \ - int _i; \ - asdl_seq *seq = (SEQ); /* avoid variable capture */ \ - for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \ - TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \ - if (!compiler_visit_ ## TYPE((C), elt)) { \ - compiler_exit_scope(c); \ - return 0; \ - } \ - } \ + int _i; \ + asdl_seq *seq = (SEQ); /* avoid variable capture */ \ + for (_i = 0; _i < asdl_seq_LEN(seq); _i++) { \ + TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, _i); \ + if (!compiler_visit_ ## TYPE((C), elt)) { \ + compiler_exit_scope(c); \ + return 0; \ + } \ + } \ } static int compiler_isdocstring(stmt_ty s) { if (s->kind != Expr_kind) - return 0; + return 0; return s->v.Expr.value->kind == Str_kind; } @@ -1143,67 +1143,67 @@ compiler_isdocstring(stmt_ty s) static int compiler_body(struct compiler *c, asdl_seq *stmts) { - int i = 0; - stmt_ty st; - - if (!asdl_seq_LEN(stmts)) - return 1; - st = (stmt_ty)asdl_seq_GET(stmts, 0); - if (compiler_isdocstring(st) && Py_OptimizeFlag < 2) { - /* don't generate docstrings if -OO */ - i = 1; - VISIT(c, expr, st->v.Expr.value); - if (!compiler_nameop(c, __doc__, Store)) - return 0; - } - for (; i < asdl_seq_LEN(stmts); i++) - VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); - return 1; + int i = 0; + stmt_ty st; + + if (!asdl_seq_LEN(stmts)) + return 1; + st = (stmt_ty)asdl_seq_GET(stmts, 0); + if (compiler_isdocstring(st) && Py_OptimizeFlag < 2) { + /* don't generate docstrings if -OO */ + i = 1; + VISIT(c, expr, st->v.Expr.value); + if (!compiler_nameop(c, __doc__, Store)) + return 0; + } + for (; i < asdl_seq_LEN(stmts); i++) + VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); + return 1; } static PyCodeObject * compiler_mod(struct compiler *c, mod_ty mod) { - PyCodeObject *co; - int addNone = 1; - static PyObject *module; - if (!module) { - module = PyUnicode_InternFromString(""); - if (!module) - return NULL; - } - /* Use 0 for firstlineno initially, will fixup in assemble(). */ - if (!compiler_enter_scope(c, module, mod, 0)) - return NULL; - switch (mod->kind) { - case Module_kind: - if (!compiler_body(c, mod->v.Module.body)) { - compiler_exit_scope(c); - return 0; - } - break; - case Interactive_kind: - c->c_interactive = 1; - VISIT_SEQ_IN_SCOPE(c, stmt, - mod->v.Interactive.body); - break; - case Expression_kind: - VISIT_IN_SCOPE(c, expr, mod->v.Expression.body); - addNone = 0; - break; - case Suite_kind: - PyErr_SetString(PyExc_SystemError, - "suite should not be possible"); - return 0; - default: - PyErr_Format(PyExc_SystemError, - "module kind %d should not be possible", - mod->kind); - return 0; - } - co = assemble(c, addNone); - compiler_exit_scope(c); - return co; + PyCodeObject *co; + int addNone = 1; + static PyObject *module; + if (!module) { + module = PyUnicode_InternFromString(""); + if (!module) + return NULL; + } + /* Use 0 for firstlineno initially, will fixup in assemble(). */ + if (!compiler_enter_scope(c, module, mod, 0)) + return NULL; + switch (mod->kind) { + case Module_kind: + if (!compiler_body(c, mod->v.Module.body)) { + compiler_exit_scope(c); + return 0; + } + break; + case Interactive_kind: + c->c_interactive = 1; + VISIT_SEQ_IN_SCOPE(c, stmt, + mod->v.Interactive.body); + break; + case Expression_kind: + VISIT_IN_SCOPE(c, expr, mod->v.Expression.body); + addNone = 0; + break; + case Suite_kind: + PyErr_SetString(PyExc_SystemError, + "suite should not be possible"); + return 0; + default: + PyErr_Format(PyExc_SystemError, + "module kind %d should not be possible", + mod->kind); + return 0; + } + co = assemble(c, addNone); + compiler_exit_scope(c); + return co; } /* The test for LOCAL must come before the test for FREE in order to @@ -1214,24 +1214,24 @@ compiler_mod(struct compiler *c, mod_ty mod) static int get_ref_type(struct compiler *c, PyObject *name) { - int scope = PyST_GetScope(c->u->u_ste, name); - if (scope == 0) { - char buf[350]; - PyOS_snprintf(buf, sizeof(buf), - "unknown scope for %.100s in %.100s(%s) in %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) - ); - Py_FatalError(buf); - } + int scope = PyST_GetScope(c->u->u_ste, name); + if (scope == 0) { + char buf[350]; + PyOS_snprintf(buf, sizeof(buf), + "unknown scope for %.100s in %.100s(%s) in %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) + ); + Py_FatalError(buf); + } - return scope; + return scope; } static int @@ -1240,636 +1240,636 @@ compiler_lookup_arg(PyObject *dict, PyObject *name) PyObject *k, *v; k = PyTuple_Pack(2, name, name->ob_type); if (k == NULL) - return -1; + return -1; v = PyDict_GetItem(dict, k); Py_DECREF(k); if (v == NULL) - return -1; + return -1; return PyLong_AS_LONG(v); } static int compiler_make_closure(struct compiler *c, PyCodeObject *co, int args) { - int i, free = PyCode_GetNumFree(co); - if (free == 0) { - ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); - ADDOP_I(c, MAKE_FUNCTION, args); - return 1; - } - for (i = 0; i < free; ++i) { - /* Bypass com_addop_varname because it will generate - LOAD_DEREF but LOAD_CLOSURE is needed. - */ - PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); - int arg, reftype; - - /* Special case: If a class contains a method with a - free variable that has the same name as a method, - the name will be considered free *and* local in the - class. It should be handled by the closure, as - well as by the normal name loookup logic. - */ - reftype = get_ref_type(c, name); - if (reftype == CELL) - arg = compiler_lookup_arg(c->u->u_cellvars, name); - else /* (reftype == FREE) */ - arg = compiler_lookup_arg(c->u->u_freevars, name); - if (arg == -1) { - fprintf(stderr, - "lookup %s in %s %d %d\n" - "freevars of %s: %s\n", - PyObject_REPR(name), - PyBytes_AS_STRING(c->u->u_name), - reftype, arg, - _PyUnicode_AsString(co->co_name), - PyObject_REPR(co->co_freevars)); - Py_FatalError("compiler_make_closure()"); - } - ADDOP_I(c, LOAD_CLOSURE, arg); - } - ADDOP_I(c, BUILD_TUPLE, free); - ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); - ADDOP_I(c, MAKE_CLOSURE, args); - return 1; + int i, free = PyCode_GetNumFree(co); + if (free == 0) { + ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); + ADDOP_I(c, MAKE_FUNCTION, args); + return 1; + } + for (i = 0; i < free; ++i) { + /* Bypass com_addop_varname because it will generate + LOAD_DEREF but LOAD_CLOSURE is needed. + */ + PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); + int arg, reftype; + + /* Special case: If a class contains a method with a + free variable that has the same name as a method, + the name will be considered free *and* local in the + class. It should be handled by the closure, as + well as by the normal name loookup logic. + */ + reftype = get_ref_type(c, name); + if (reftype == CELL) + arg = compiler_lookup_arg(c->u->u_cellvars, name); + else /* (reftype == FREE) */ + arg = compiler_lookup_arg(c->u->u_freevars, name); + if (arg == -1) { + fprintf(stderr, + "lookup %s in %s %d %d\n" + "freevars of %s: %s\n", + PyObject_REPR(name), + PyBytes_AS_STRING(c->u->u_name), + reftype, arg, + _PyUnicode_AsString(co->co_name), + PyObject_REPR(co->co_freevars)); + Py_FatalError("compiler_make_closure()"); + } + ADDOP_I(c, LOAD_CLOSURE, arg); + } + ADDOP_I(c, BUILD_TUPLE, free); + ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts); + ADDOP_I(c, MAKE_CLOSURE, args); + return 1; } static int compiler_decorators(struct compiler *c, asdl_seq* decos) { - int i; + int i; - if (!decos) - return 1; + if (!decos) + return 1; - for (i = 0; i < asdl_seq_LEN(decos); i++) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(decos, i)); - } - return 1; + for (i = 0; i < asdl_seq_LEN(decos); i++) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(decos, i)); + } + return 1; } static int compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, - asdl_seq *kw_defaults) -{ - int i, default_count = 0; - for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { - arg_ty arg = asdl_seq_GET(kwonlyargs, i); - expr_ty default_ = asdl_seq_GET(kw_defaults, i); - if (default_) { - ADDOP_O(c, LOAD_CONST, arg->arg, consts); - if (!compiler_visit_expr(c, default_)) { - return -1; - } - default_count++; - } - } - return default_count; + asdl_seq *kw_defaults) +{ + int i, default_count = 0; + for (i = 0; i < asdl_seq_LEN(kwonlyargs); i++) { + arg_ty arg = asdl_seq_GET(kwonlyargs, i); + expr_ty default_ = asdl_seq_GET(kw_defaults, i); + if (default_) { + ADDOP_O(c, LOAD_CONST, arg->arg, consts); + if (!compiler_visit_expr(c, default_)) { + return -1; + } + default_count++; + } + } + return default_count; } static int compiler_visit_argannotation(struct compiler *c, identifier id, expr_ty annotation, PyObject *names) { - if (annotation) { - VISIT(c, expr, annotation); - if (PyList_Append(names, id)) - return -1; - } - return 0; + if (annotation) { + VISIT(c, expr, annotation); + if (PyList_Append(names, id)) + return -1; + } + return 0; } static int compiler_visit_argannotations(struct compiler *c, asdl_seq* args, PyObject *names) { - int i, error; - for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - error = compiler_visit_argannotation( - c, - arg->arg, - arg->annotation, - names); - if (error) - return error; - } - return 0; + int i, error; + for (i = 0; i < asdl_seq_LEN(args); i++) { + arg_ty arg = (arg_ty)asdl_seq_GET(args, i); + error = compiler_visit_argannotation( + c, + arg->arg, + arg->annotation, + names); + if (error) + return error; + } + return 0; } static int compiler_visit_annotations(struct compiler *c, arguments_ty args, expr_ty returns) { - /* Push arg annotations and a list of the argument names. Return the # - of items pushed. The expressions are evaluated out-of-order wrt the - source code. - - More than 2^16-1 annotations is a SyntaxError. Returns -1 on error. - */ - static identifier return_str; - PyObject *names; - int len; - names = PyList_New(0); - if (!names) - return -1; - - if (compiler_visit_argannotations(c, args->args, names)) - goto error; - if (args->varargannotation && - compiler_visit_argannotation(c, args->vararg, - args->varargannotation, 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)) - goto error; - - if (!return_str) { - return_str = PyUnicode_InternFromString("return"); - if (!return_str) - goto error; - } - if (compiler_visit_argannotation(c, return_str, returns, names)) { - goto error; - } - - len = PyList_GET_SIZE(names); - if (len > 65534) { - /* len must fit in 16 bits, and len is incremented below */ - PyErr_SetString(PyExc_SyntaxError, - "too many annotations"); - goto error; - } - if (len) { - /* convert names to a tuple and place on stack */ - PyObject *elt; - int i; - PyObject *s = PyTuple_New(len); - if (!s) - goto error; - for (i = 0; i < len; i++) { - elt = PyList_GET_ITEM(names, i); - Py_INCREF(elt); - PyTuple_SET_ITEM(s, i, elt); - } - ADDOP_O(c, LOAD_CONST, s, consts); - Py_DECREF(s); - len++; /* include the just-pushed tuple */ - } - Py_DECREF(names); - return len; + /* Push arg annotations and a list of the argument names. Return the # + of items pushed. The expressions are evaluated out-of-order wrt the + source code. + + More than 2^16-1 annotations is a SyntaxError. Returns -1 on error. + */ + static identifier return_str; + PyObject *names; + int len; + names = PyList_New(0); + if (!names) + return -1; + + if (compiler_visit_argannotations(c, args->args, names)) + goto error; + if (args->varargannotation && + compiler_visit_argannotation(c, args->vararg, + args->varargannotation, 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)) + goto error; + + if (!return_str) { + return_str = PyUnicode_InternFromString("return"); + if (!return_str) + goto error; + } + if (compiler_visit_argannotation(c, return_str, returns, names)) { + goto error; + } + + len = PyList_GET_SIZE(names); + if (len > 65534) { + /* len must fit in 16 bits, and len is incremented below */ + PyErr_SetString(PyExc_SyntaxError, + "too many annotations"); + goto error; + } + if (len) { + /* convert names to a tuple and place on stack */ + PyObject *elt; + int i; + PyObject *s = PyTuple_New(len); + if (!s) + goto error; + for (i = 0; i < len; i++) { + elt = PyList_GET_ITEM(names, i); + Py_INCREF(elt); + PyTuple_SET_ITEM(s, i, elt); + } + ADDOP_O(c, LOAD_CONST, s, consts); + Py_DECREF(s); + len++; /* include the just-pushed tuple */ + } + Py_DECREF(names); + return len; error: - Py_DECREF(names); - return -1; + Py_DECREF(names); + return -1; } static int compiler_function(struct compiler *c, stmt_ty s) { - PyCodeObject *co; - PyObject *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; - stmt_ty st; - int i, n, docstring, kw_default_count = 0, arglength; - int num_annotations; - - assert(s->kind == FunctionDef_kind); - - if (!compiler_decorators(c, decos)) - return 0; - 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); - num_annotations = compiler_visit_annotations(c, args, returns); - if (num_annotations < 0) - return 0; - assert((num_annotations & 0xFFFF) == num_annotations); - - if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, - s->lineno)) - return 0; - - st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0); - docstring = compiler_isdocstring(st); - if (docstring && Py_OptimizeFlag < 2) - 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; - } - - 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); - /* 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); - VISIT_IN_SCOPE(c, stmt, st); - } - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - arglength = asdl_seq_LEN(args->defaults); - arglength |= kw_default_count << 8; - arglength |= num_annotations << 16; - compiler_make_closure(c, co, arglength); - Py_DECREF(co); - - /* 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); + PyCodeObject *co; + PyObject *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; + stmt_ty st; + int i, n, docstring, kw_default_count = 0, arglength; + int num_annotations; + + assert(s->kind == FunctionDef_kind); + + if (!compiler_decorators(c, decos)) + return 0; + 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); + num_annotations = compiler_visit_annotations(c, args, returns); + if (num_annotations < 0) + return 0; + assert((num_annotations & 0xFFFF) == num_annotations); + + if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, + s->lineno)) + return 0; + + st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0); + docstring = compiler_isdocstring(st); + if (docstring && Py_OptimizeFlag < 2) + 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; + } + + 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); + /* 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); + VISIT_IN_SCOPE(c, stmt, st); + } + co = assemble(c, 1); + compiler_exit_scope(c); + if (co == NULL) + return 0; + + arglength = asdl_seq_LEN(args->defaults); + arglength |= kw_default_count << 8; + arglength |= num_annotations << 16; + compiler_make_closure(c, co, arglength); + Py_DECREF(co); + + /* 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); } static int compiler_class(struct compiler *c, stmt_ty s) { - PyCodeObject *co; - PyObject *str; - int i; - asdl_seq* decos = s->v.ClassDef.decorator_list; - - if (!compiler_decorators(c, decos)) - return 0; - - /* ultimately generate code for: - = __build_class__(, , *, **) - where: - is a function/closure created from the class body; - it has a single argument (__locals__) where the dict - (or MutableSequence) representing the locals is passed - is the class name - is the positional arguments and *varargs argument - is the keyword arguments and **kwds argument - This borrows from compiler_call. - */ - - /* 1. compile the class body into a code object */ - if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) - return 0; - /* this block represents what we do in the new scope */ - { - /* use the class name for name mangling */ - 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)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - Py_DECREF(str); - /* ... and store it as __module__ */ - str = PyUnicode_InternFromString("__module__"); - if (!str || !compiler_nameop(c, str, Store)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - Py_DECREF(str); - /* compile the body proper */ - if (!compiler_body(c, s->v.ClassDef.body)) { - 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 { - /* Return the cell where to store __class__ */ - ADDOP_I(c, LOAD_CLOSURE, i); - } - ADDOP_IN_SCOPE(c, RETURN_VALUE); - /* create the code object */ - co = assemble(c, 1); - } - /* leave the new scope */ - compiler_exit_scope(c); - if (co == NULL) - return 0; - - /* 2. load the 'build_class' function */ - ADDOP(c, LOAD_BUILD_CLASS); - - /* 3. load a function (or closure) made from the code object */ - compiler_make_closure(c, co, 0); - Py_DECREF(co); - - /* 4. load class name */ - ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); - - /* 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)) - return 0; - - /* 6. apply decorators */ - for (i = 0; i < asdl_seq_LEN(decos); i++) { - ADDOP_I(c, CALL_FUNCTION, 1); + PyCodeObject *co; + PyObject *str; + int i; + asdl_seq* decos = s->v.ClassDef.decorator_list; + + if (!compiler_decorators(c, decos)) + return 0; + + /* ultimately generate code for: + = __build_class__(, , *, **) + where: + is a function/closure created from the class body; + it has a single argument (__locals__) where the dict + (or MutableSequence) representing the locals is passed + is the class name + is the positional arguments and *varargs argument + is the keyword arguments and **kwds argument + This borrows from compiler_call. + */ + + /* 1. compile the class body into a code object */ + if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, s->lineno)) + return 0; + /* this block represents what we do in the new scope */ + { + /* use the class name for name mangling */ + 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)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); + /* ... and store it as __module__ */ + str = PyUnicode_InternFromString("__module__"); + if (!str || !compiler_nameop(c, str, Store)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } + Py_DECREF(str); + /* compile the body proper */ + if (!compiler_body(c, s->v.ClassDef.body)) { + 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 { + /* Return the cell where to store __class__ */ + ADDOP_I(c, LOAD_CLOSURE, i); } + ADDOP_IN_SCOPE(c, RETURN_VALUE); + /* create the code object */ + co = assemble(c, 1); + } + /* leave the new scope */ + compiler_exit_scope(c); + if (co == NULL) + return 0; + + /* 2. load the 'build_class' function */ + ADDOP(c, LOAD_BUILD_CLASS); + + /* 3. load a function (or closure) made from the code object */ + compiler_make_closure(c, co, 0); + Py_DECREF(co); + + /* 4. load class name */ + ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); + + /* 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)) + return 0; + + /* 6. apply decorators */ + for (i = 0; i < asdl_seq_LEN(decos); i++) { + ADDOP_I(c, CALL_FUNCTION, 1); + } - /* 7. store into */ - if (!compiler_nameop(c, s->v.ClassDef.name, Store)) - return 0; - return 1; + /* 7. store into */ + if (!compiler_nameop(c, s->v.ClassDef.name, Store)) + return 0; + return 1; } static int compiler_ifexp(struct compiler *c, expr_ty e) { - basicblock *end, *next; - - assert(e->kind == IfExp_kind); - end = compiler_new_block(c); - if (end == NULL) - return 0; - next = compiler_new_block(c); - if (next == NULL) - return 0; - VISIT(c, expr, e->v.IfExp.test); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, next); - VISIT(c, expr, e->v.IfExp.body); - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, next); - VISIT(c, expr, e->v.IfExp.orelse); - compiler_use_next_block(c, end); - return 1; + basicblock *end, *next; + + assert(e->kind == IfExp_kind); + end = compiler_new_block(c); + if (end == NULL) + return 0; + next = compiler_new_block(c); + if (next == NULL) + return 0; + VISIT(c, expr, e->v.IfExp.test); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, next); + VISIT(c, expr, e->v.IfExp.body); + ADDOP_JREL(c, JUMP_FORWARD, end); + compiler_use_next_block(c, next); + VISIT(c, expr, e->v.IfExp.orelse); + compiler_use_next_block(c, end); + return 1; } static int compiler_lambda(struct compiler *c, expr_ty e) { - PyCodeObject *co; - static identifier name; - int kw_default_count = 0, arglength; - arguments_ty args = e->v.Lambda.args; - assert(e->kind == Lambda_kind); - - if (!name) { - name = PyUnicode_InternFromString(""); - if (!name) - return 0; - } - - 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, (void *)e, e->lineno)) - return 0; - - /* Make None the first constant, so the lambda can't have a - docstring. */ - if (compiler_add_o(c, c->u->u_consts, Py_None) < 0) - return 0; - - c->u->u_argcount = asdl_seq_LEN(args->args); - c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); - if (c->u->u_ste->ste_generator) { - ADDOP_IN_SCOPE(c, POP_TOP); - } - else { - ADDOP_IN_SCOPE(c, RETURN_VALUE); - } - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - return 0; - - arglength = asdl_seq_LEN(args->defaults); - arglength |= kw_default_count << 8; - compiler_make_closure(c, co, arglength); - Py_DECREF(co); - - return 1; + PyCodeObject *co; + static identifier name; + int kw_default_count = 0, arglength; + arguments_ty args = e->v.Lambda.args; + assert(e->kind == Lambda_kind); + + if (!name) { + name = PyUnicode_InternFromString(""); + if (!name) + return 0; + } + + 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, (void *)e, e->lineno)) + return 0; + + /* Make None the first constant, so the lambda can't have a + docstring. */ + if (compiler_add_o(c, c->u->u_consts, Py_None) < 0) + return 0; + + c->u->u_argcount = asdl_seq_LEN(args->args); + c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); + VISIT_IN_SCOPE(c, expr, e->v.Lambda.body); + if (c->u->u_ste->ste_generator) { + ADDOP_IN_SCOPE(c, POP_TOP); + } + else { + ADDOP_IN_SCOPE(c, RETURN_VALUE); + } + co = assemble(c, 1); + compiler_exit_scope(c); + if (co == NULL) + return 0; + + arglength = asdl_seq_LEN(args->defaults); + arglength |= kw_default_count << 8; + compiler_make_closure(c, co, arglength); + Py_DECREF(co); + + return 1; } static int compiler_if(struct compiler *c, stmt_ty s) { - basicblock *end, *next; - int constant; - assert(s->kind == If_kind); - end = compiler_new_block(c); - if (end == NULL) - return 0; - - constant = expr_constant(s->v.If.test); - /* constant = 0: "if 0" - * constant = 1: "if 1", "if 2", ... - * constant = -1: rest */ - if (constant == 0) { - if (s->v.If.orelse) - VISIT_SEQ(c, stmt, s->v.If.orelse); - } else if (constant == 1) { - VISIT_SEQ(c, stmt, s->v.If.body); - } else { - if (s->v.If.orelse) { - next = compiler_new_block(c); - if (next == NULL) - return 0; - } - else - next = end; - 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) { - compiler_use_next_block(c, next); - VISIT_SEQ(c, stmt, s->v.If.orelse); - } - } - compiler_use_next_block(c, end); - return 1; + basicblock *end, *next; + int constant; + assert(s->kind == If_kind); + end = compiler_new_block(c); + if (end == NULL) + return 0; + + constant = expr_constant(s->v.If.test); + /* constant = 0: "if 0" + * constant = 1: "if 1", "if 2", ... + * constant = -1: rest */ + if (constant == 0) { + if (s->v.If.orelse) + VISIT_SEQ(c, stmt, s->v.If.orelse); + } else if (constant == 1) { + VISIT_SEQ(c, stmt, s->v.If.body); + } else { + if (s->v.If.orelse) { + next = compiler_new_block(c); + if (next == NULL) + return 0; + } + else + next = end; + 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) { + compiler_use_next_block(c, next); + VISIT_SEQ(c, stmt, s->v.If.orelse); + } + } + compiler_use_next_block(c, end); + return 1; } static int compiler_for(struct compiler *c, stmt_ty s) { - basicblock *start, *cleanup, *end; - - start = compiler_new_block(c); - cleanup = compiler_new_block(c); - end = compiler_new_block(c); - if (start == NULL || end == NULL || cleanup == NULL) - return 0; - ADDOP_JREL(c, SETUP_LOOP, end); - if (!compiler_push_fblock(c, LOOP, start)) - return 0; - VISIT(c, expr, s->v.For.iter); - ADDOP(c, GET_ITER); - compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, cleanup); - VISIT(c, expr, s->v.For.target); - VISIT_SEQ(c, stmt, s->v.For.body); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - compiler_use_next_block(c, cleanup); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, LOOP, start); - VISIT_SEQ(c, stmt, s->v.For.orelse); - compiler_use_next_block(c, end); - return 1; + basicblock *start, *cleanup, *end; + + start = compiler_new_block(c); + cleanup = compiler_new_block(c); + end = compiler_new_block(c); + if (start == NULL || end == NULL || cleanup == NULL) + return 0; + ADDOP_JREL(c, SETUP_LOOP, end); + if (!compiler_push_fblock(c, LOOP, start)) + return 0; + VISIT(c, expr, s->v.For.iter); + ADDOP(c, GET_ITER); + compiler_use_next_block(c, start); + ADDOP_JREL(c, FOR_ITER, cleanup); + VISIT(c, expr, s->v.For.target); + VISIT_SEQ(c, stmt, s->v.For.body); + ADDOP_JABS(c, JUMP_ABSOLUTE, start); + compiler_use_next_block(c, cleanup); + ADDOP(c, POP_BLOCK); + compiler_pop_fblock(c, LOOP, start); + 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) { - basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = expr_constant(s->v.While.test); - - if (constant == 0) { - if (s->v.While.orelse) - VISIT_SEQ(c, stmt, s->v.While.orelse); - return 1; - } - loop = compiler_new_block(c); - end = compiler_new_block(c); - if (constant == -1) { - anchor = compiler_new_block(c); - if (anchor == NULL) - return 0; - } - if (loop == NULL || end == NULL) - return 0; - if (s->v.While.orelse) { - orelse = compiler_new_block(c); - if (orelse == NULL) - return 0; - } - else - orelse = NULL; - - ADDOP_JREL(c, SETUP_LOOP, end); - compiler_use_next_block(c, loop); - if (!compiler_push_fblock(c, LOOP, loop)) - return 0; - if (constant == -1) { - VISIT(c, expr, s->v.While.test); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, anchor); - } - VISIT_SEQ(c, stmt, s->v.While.body); - ADDOP_JABS(c, JUMP_ABSOLUTE, loop); - - /* XXX should the two POP instructions be in a separate block - if there is no else clause ? - */ - - if (constant == -1) { - compiler_use_next_block(c, anchor); - ADDOP(c, POP_BLOCK); - } - compiler_pop_fblock(c, LOOP, loop); - if (orelse != NULL) /* what if orelse is just pass? */ - VISIT_SEQ(c, stmt, s->v.While.orelse); - compiler_use_next_block(c, end); - - return 1; + basicblock *loop, *orelse, *end, *anchor = NULL; + int constant = expr_constant(s->v.While.test); + + if (constant == 0) { + if (s->v.While.orelse) + VISIT_SEQ(c, stmt, s->v.While.orelse); + return 1; + } + loop = compiler_new_block(c); + end = compiler_new_block(c); + if (constant == -1) { + anchor = compiler_new_block(c); + if (anchor == NULL) + return 0; + } + if (loop == NULL || end == NULL) + return 0; + if (s->v.While.orelse) { + orelse = compiler_new_block(c); + if (orelse == NULL) + return 0; + } + else + orelse = NULL; + + ADDOP_JREL(c, SETUP_LOOP, end); + compiler_use_next_block(c, loop); + if (!compiler_push_fblock(c, LOOP, loop)) + return 0; + if (constant == -1) { + VISIT(c, expr, s->v.While.test); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, anchor); + } + VISIT_SEQ(c, stmt, s->v.While.body); + ADDOP_JABS(c, JUMP_ABSOLUTE, loop); + + /* XXX should the two POP instructions be in a separate block + if there is no else clause ? + */ + + if (constant == -1) { + compiler_use_next_block(c, anchor); + ADDOP(c, POP_BLOCK); + } + compiler_pop_fblock(c, LOOP, loop); + if (orelse != NULL) /* what if orelse is just pass? */ + VISIT_SEQ(c, stmt, s->v.While.orelse); + compiler_use_next_block(c, end); + + return 1; } static int compiler_continue(struct compiler *c) { - static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop"; - static const char IN_FINALLY_ERROR_MSG[] = - "'continue' not supported inside 'finally' clause"; - int i; - - if (!c->u->u_nfblocks) - return compiler_error(c, LOOP_ERROR_MSG); - i = c->u->u_nfblocks - 1; - switch (c->u->u_fblock[i].fb_type) { - case LOOP: - ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); - break; - case EXCEPT: - case FINALLY_TRY: - while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) { - /* Prevent continue anywhere under a finally - even if hidden in a sub-try or except. */ - if (c->u->u_fblock[i].fb_type == FINALLY_END) - return compiler_error(c, IN_FINALLY_ERROR_MSG); - } - if (i == -1) - return compiler_error(c, LOOP_ERROR_MSG); - ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); - break; - case FINALLY_END: - return compiler_error(c, IN_FINALLY_ERROR_MSG); - } - - return 1; + static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop"; + static const char IN_FINALLY_ERROR_MSG[] = + "'continue' not supported inside 'finally' clause"; + int i; + + if (!c->u->u_nfblocks) + return compiler_error(c, LOOP_ERROR_MSG); + i = c->u->u_nfblocks - 1; + switch (c->u->u_fblock[i].fb_type) { + case LOOP: + ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); + break; + case EXCEPT: + case FINALLY_TRY: + while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) { + /* Prevent continue anywhere under a finally + even if hidden in a sub-try or except. */ + if (c->u->u_fblock[i].fb_type == FINALLY_END) + return compiler_error(c, IN_FINALLY_ERROR_MSG); + } + if (i == -1) + return compiler_error(c, LOOP_ERROR_MSG); + ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); + break; + case FINALLY_END: + return compiler_error(c, IN_FINALLY_ERROR_MSG); + } + + return 1; } /* Code generated for "try: finally: " is as follows: - - SETUP_FINALLY L - - POP_BLOCK - LOAD_CONST - L: - END_FINALLY - + + SETUP_FINALLY L + + POP_BLOCK + LOAD_CONST + L: + END_FINALLY + The special instructions use the block stack. Each block stack entry contains the instruction that created it (here SETUP_FINALLY), the level of the value stack at the time the block stack entry was created, and a label (here L). - + SETUP_FINALLY: - Pushes the current value stack level and the label - onto the block stack. + Pushes the current value stack level and the label + onto the block stack. POP_BLOCK: - Pops en entry from the block stack, and pops the value - stack until its level is the same as indicated on the - block stack. (The label is ignored.) + Pops en entry from the block stack, and pops the value + stack until its level is the same as indicated on the + block stack. (The label is ignored.) END_FINALLY: - Pops a variable number of entries from the *value* stack - and re-raises the exception they specify. The number of - entries popped depends on the (pseudo) exception type. - + Pops a variable number of entries from the *value* stack + and re-raises the exception they specify. The number of + entries popped depends on the (pseudo) exception type. + The block stack is unwound when an exception is raised: when a SETUP_FINALLY entry is found, the exception is pushed onto the value stack (and the exception condition is cleared), @@ -1880,29 +1880,29 @@ compiler_continue(struct compiler *c) static int compiler_try_finally(struct compiler *c, stmt_ty s) { - basicblock *body, *end; - body = compiler_new_block(c); - end = compiler_new_block(c); - if (body == NULL || end == NULL) - return 0; - - ADDOP_JREL(c, SETUP_FINALLY, end); - compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, FINALLY_TRY, body)) - return 0; - VISIT_SEQ(c, stmt, s->v.TryFinally.body); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, body); + basicblock *body, *end; + body = compiler_new_block(c); + end = compiler_new_block(c); + if (body == NULL || end == NULL) + return 0; + + ADDOP_JREL(c, SETUP_FINALLY, end); + compiler_use_next_block(c, body); + if (!compiler_push_fblock(c, FINALLY_TRY, body)) + return 0; + VISIT_SEQ(c, stmt, s->v.TryFinally.body); + ADDOP(c, POP_BLOCK); + compiler_pop_fblock(c, FINALLY_TRY, body); - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_use_next_block(c, end); - if (!compiler_push_fblock(c, FINALLY_END, end)) - return 0; - VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, end); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, end); + if (!compiler_push_fblock(c, FINALLY_END, end)) + return 0; + VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, end); - return 1; + return 1; } /* @@ -1910,864 +1910,864 @@ compiler_try_finally(struct compiler *c, stmt_ty s) (The contents of the value stack is shown in [], with the top at the right; 'tb' is trace-back info, 'val' the exception's associated value, and 'exc' the exception.) - - Value stack Label Instruction Argument - [] SETUP_EXCEPT L1 - [] - [] POP_BLOCK - [] JUMP_FORWARD L0 - - [tb, val, exc] L1: DUP ) - [tb, val, exc, exc] ) - [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 - [tb, val, exc, 1-or-0] POP_JUMP_IF_FALSE L2 ) - [tb, val, exc] POP - [tb, val] (or POP if no V1) - [tb] POP - [] - JUMP_FORWARD L0 - - [tb, val, exc] L2: DUP + + Value stack Label Instruction Argument + [] SETUP_EXCEPT L1 + [] + [] POP_BLOCK + [] JUMP_FORWARD L0 + + [tb, val, exc] L1: DUP ) + [tb, val, exc, exc] ) + [tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1 + [tb, val, exc, 1-or-0] POP_JUMP_IF_FALSE L2 ) + [tb, val, exc] POP + [tb, val] (or POP if no V1) + [tb] POP + [] + JUMP_FORWARD L0 + + [tb, val, exc] L2: DUP .............................etc....................... - [tb, val, exc] Ln+1: END_FINALLY # re-raise exception - - [] L0: - + [tb, val, exc] Ln+1: END_FINALLY # re-raise exception + + [] L0: + Of course, parts are not generated if Vi or Ei is not present. */ static int compiler_try_except(struct compiler *c, stmt_ty s) { - basicblock *body, *orelse, *except, *end; - int i, n; - - body = compiler_new_block(c); - except = compiler_new_block(c); - orelse = compiler_new_block(c); - end = compiler_new_block(c); - if (body == NULL || except == NULL || orelse == NULL || end == NULL) - return 0; - ADDOP_JREL(c, SETUP_EXCEPT, except); - compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, EXCEPT, body)) - return 0; - VISIT_SEQ(c, stmt, s->v.TryExcept.body); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, EXCEPT, body); - ADDOP_JREL(c, JUMP_FORWARD, orelse); - n = asdl_seq_LEN(s->v.TryExcept.handlers); - compiler_use_next_block(c, except); - for (i = 0; i < n; i++) { - excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( - s->v.TryExcept.handlers, i); - if (!handler->v.ExceptHandler.type && i < n-1) - return compiler_error(c, "default 'except:' must be last"); - c->u->u_lineno_set = 0; - c->u->u_lineno = handler->lineno; - except = compiler_new_block(c); - if (except == NULL) - return 0; - if (handler->v.ExceptHandler.type) { - ADDOP(c, DUP_TOP); - VISIT(c, expr, handler->v.ExceptHandler.type); - ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, except); - } - ADDOP(c, POP_TOP); - if (handler->v.ExceptHandler.name) { - basicblock *cleanup_end, *cleanup_body; - - cleanup_end = compiler_new_block(c); - cleanup_body = compiler_new_block(c); - if(!(cleanup_end || cleanup_body)) - return 0; - - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); + basicblock *body, *orelse, *except, *end; + int i, n; + + body = compiler_new_block(c); + except = compiler_new_block(c); + orelse = compiler_new_block(c); + end = compiler_new_block(c); + if (body == NULL || except == NULL || orelse == NULL || end == NULL) + return 0; + ADDOP_JREL(c, SETUP_EXCEPT, except); + compiler_use_next_block(c, body); + if (!compiler_push_fblock(c, EXCEPT, body)) + return 0; + VISIT_SEQ(c, stmt, s->v.TryExcept.body); + ADDOP(c, POP_BLOCK); + compiler_pop_fblock(c, EXCEPT, body); + ADDOP_JREL(c, JUMP_FORWARD, orelse); + n = asdl_seq_LEN(s->v.TryExcept.handlers); + compiler_use_next_block(c, except); + for (i = 0; i < n; i++) { + excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( + s->v.TryExcept.handlers, i); + if (!handler->v.ExceptHandler.type && i < n-1) + return compiler_error(c, "default 'except:' must be last"); + c->u->u_lineno_set = 0; + c->u->u_lineno = handler->lineno; + except = compiler_new_block(c); + if (except == NULL) + return 0; + if (handler->v.ExceptHandler.type) { + ADDOP(c, DUP_TOP); + VISIT(c, expr, handler->v.ExceptHandler.type); + ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, except); + } + ADDOP(c, POP_TOP); + if (handler->v.ExceptHandler.name) { + basicblock *cleanup_end, *cleanup_body; - /* - try: - # body - except type as name: - try: - # body - finally: - name = None - del name - */ - - /* second try: */ - ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); - compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) - return 0; - - /* second # body */ - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - ADDOP(c, POP_BLOCK); - ADDOP(c, POP_EXCEPT); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); - - /* finally: */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_use_next_block(c, cleanup_end); - if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) - return 0; - - /* name = None */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - compiler_nameop(c, handler->v.ExceptHandler.name, Store); + cleanup_end = compiler_new_block(c); + cleanup_body = compiler_new_block(c); + if(!(cleanup_end || cleanup_body)) + return 0; - /* del name */ - compiler_nameop(c, handler->v.ExceptHandler.name, Del); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + ADDOP(c, POP_TOP); - ADDOP(c, END_FINALLY); - compiler_pop_fblock(c, FINALLY_END, cleanup_end); - } - else { - basicblock *cleanup_body; + /* + try: + # body + except type as name: + try: + # body + finally: + name = None + del name + */ + + /* second try: */ + ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); + compiler_use_next_block(c, cleanup_body); + if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + return 0; + + /* second # body */ + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + ADDOP(c, POP_BLOCK); + ADDOP(c, POP_EXCEPT); + compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + + /* finally: */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, cleanup_end); + if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) + return 0; + + /* name = None */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_nameop(c, handler->v.ExceptHandler.name, Store); + + /* del name */ + compiler_nameop(c, handler->v.ExceptHandler.name, Del); + + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, cleanup_end); + } + else { + basicblock *cleanup_body; - cleanup_body = compiler_new_block(c); - if(!cleanup_body) - return 0; + cleanup_body = compiler_new_block(c); + if(!cleanup_body) + return 0; - ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) - return 0; - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - ADDOP(c, POP_EXCEPT); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); - } - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, except); - } - ADDOP(c, END_FINALLY); - compiler_use_next_block(c, orelse); - VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); - compiler_use_next_block(c, end); - return 1; + ADDOP(c, POP_TOP); + compiler_use_next_block(c, cleanup_body); + if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + return 0; + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + ADDOP(c, POP_EXCEPT); + compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + } + ADDOP_JREL(c, JUMP_FORWARD, end); + compiler_use_next_block(c, except); + } + ADDOP(c, END_FINALLY); + compiler_use_next_block(c, orelse); + VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); + compiler_use_next_block(c, end); + return 1; } static int compiler_import_as(struct compiler *c, identifier name, identifier asname) { - /* The IMPORT_NAME opcode was already generated. This function - merely needs to bind the result to a name. - - If there is a dot in name, we need to split it and emit a - LOAD_ATTR for each name. - */ - const Py_UNICODE *src = PyUnicode_AS_UNICODE(name); - const Py_UNICODE *dot = Py_UNICODE_strchr(src, '.'); - if (dot) { - /* Consume the base module name to get the first attribute */ - src = dot + 1; - while (dot) { - /* NB src is only defined when dot != NULL */ - PyObject *attr; - dot = Py_UNICODE_strchr(src, '.'); - attr = PyUnicode_FromUnicode(src, - dot ? dot - src : Py_UNICODE_strlen(src)); - if (!attr) - return -1; - ADDOP_O(c, LOAD_ATTR, attr, names); - Py_DECREF(attr); - src = dot + 1; - } - } - return compiler_nameop(c, asname, Store); + /* The IMPORT_NAME opcode was already generated. This function + merely needs to bind the result to a name. + + If there is a dot in name, we need to split it and emit a + LOAD_ATTR for each name. + */ + const Py_UNICODE *src = PyUnicode_AS_UNICODE(name); + const Py_UNICODE *dot = Py_UNICODE_strchr(src, '.'); + if (dot) { + /* Consume the base module name to get the first attribute */ + src = dot + 1; + while (dot) { + /* NB src is only defined when dot != NULL */ + PyObject *attr; + dot = Py_UNICODE_strchr(src, '.'); + attr = PyUnicode_FromUnicode(src, + dot ? dot - src : Py_UNICODE_strlen(src)); + if (!attr) + return -1; + ADDOP_O(c, LOAD_ATTR, attr, names); + Py_DECREF(attr); + src = dot + 1; + } + } + return compiler_nameop(c, asname, Store); } static int compiler_import(struct compiler *c, stmt_ty s) { - /* The Import node stores a module name like a.b.c as a single - string. This is convenient for all cases except - import a.b.c as d - where we need to parse that string to extract the individual - module names. - XXX Perhaps change the representation to make this case simpler? - */ - int i, n = asdl_seq_LEN(s->v.Import.names); - - for (i = 0; i < n; i++) { - alias_ty alias = (alias_ty)asdl_seq_GET(s->v.Import.names, i); - int r; - PyObject *level; - - level = PyLong_FromLong(0); - if (level == NULL) - return 0; - - ADDOP_O(c, LOAD_CONST, level, consts); - Py_DECREF(level); - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP_NAME(c, IMPORT_NAME, alias->name, names); - - if (alias->asname) { - r = compiler_import_as(c, alias->name, alias->asname); - if (!r) - return r; - } - else { - identifier tmp = alias->name; - const Py_UNICODE *base = PyUnicode_AS_UNICODE(alias->name); - Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); - if (dot) - tmp = PyUnicode_FromUnicode(base, - dot - base); - r = compiler_nameop(c, tmp, Store); - if (dot) { - Py_DECREF(tmp); - } - if (!r) - return r; - } - } - return 1; + /* The Import node stores a module name like a.b.c as a single + string. This is convenient for all cases except + import a.b.c as d + where we need to parse that string to extract the individual + module names. + XXX Perhaps change the representation to make this case simpler? + */ + int i, n = asdl_seq_LEN(s->v.Import.names); + + for (i = 0; i < n; i++) { + alias_ty alias = (alias_ty)asdl_seq_GET(s->v.Import.names, i); + int r; + PyObject *level; + + level = PyLong_FromLong(0); + if (level == NULL) + return 0; + + ADDOP_O(c, LOAD_CONST, level, consts); + Py_DECREF(level); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP_NAME(c, IMPORT_NAME, alias->name, names); + + if (alias->asname) { + r = compiler_import_as(c, alias->name, alias->asname); + if (!r) + return r; + } + else { + identifier tmp = alias->name; + const Py_UNICODE *base = PyUnicode_AS_UNICODE(alias->name); + Py_UNICODE *dot = Py_UNICODE_strchr(base, '.'); + if (dot) + tmp = PyUnicode_FromUnicode(base, + dot - base); + r = compiler_nameop(c, tmp, Store); + if (dot) { + Py_DECREF(tmp); + } + if (!r) + return r; + } + } + return 1; } static int compiler_from_import(struct compiler *c, stmt_ty s) { - int i, n = asdl_seq_LEN(s->v.ImportFrom.names); - - PyObject *names = PyTuple_New(n); - PyObject *level; - static PyObject *empty_string; - - if (!empty_string) { - empty_string = PyUnicode_FromString(""); - if (!empty_string) - return 0; - } - - if (!names) - return 0; - - level = PyLong_FromLong(s->v.ImportFrom.level); - if (!level) { - Py_DECREF(names); - return 0; - } - - /* build up the names */ - for (i = 0; i < n; i++) { - alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); - Py_INCREF(alias->name); - PyTuple_SET_ITEM(names, i, alias->name); - } - - if (s->lineno > c->c_future->ff_lineno && s->v.ImportFrom.module && - !PyUnicode_CompareWithASCIIString(s->v.ImportFrom.module, "__future__")) { - Py_DECREF(level); - Py_DECREF(names); - return compiler_error(c, "from __future__ imports must occur " - "at the beginning of the file"); - } - - ADDOP_O(c, LOAD_CONST, level, consts); - Py_DECREF(level); - ADDOP_O(c, LOAD_CONST, names, consts); - Py_DECREF(names); - if (s->v.ImportFrom.module) { - ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); - } - else { - ADDOP_NAME(c, IMPORT_NAME, empty_string, names); - } - for (i = 0; i < n; i++) { - alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); - identifier store_name; - - if (i == 0 && *PyUnicode_AS_UNICODE(alias->name) == '*') { - assert(n == 1); - ADDOP(c, IMPORT_STAR); - return 1; - } - - ADDOP_NAME(c, IMPORT_FROM, alias->name, names); - store_name = alias->name; - if (alias->asname) - store_name = alias->asname; - - if (!compiler_nameop(c, store_name, Store)) { - Py_DECREF(names); - return 0; - } - } - /* remove imported module */ - ADDOP(c, POP_TOP); - return 1; + int i, n = asdl_seq_LEN(s->v.ImportFrom.names); + + PyObject *names = PyTuple_New(n); + PyObject *level; + static PyObject *empty_string; + + if (!empty_string) { + empty_string = PyUnicode_FromString(""); + if (!empty_string) + return 0; + } + + if (!names) + return 0; + + level = PyLong_FromLong(s->v.ImportFrom.level); + if (!level) { + Py_DECREF(names); + return 0; + } + + /* build up the names */ + for (i = 0; i < n; i++) { + alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); + Py_INCREF(alias->name); + PyTuple_SET_ITEM(names, i, alias->name); + } + + if (s->lineno > c->c_future->ff_lineno && s->v.ImportFrom.module && + !PyUnicode_CompareWithASCIIString(s->v.ImportFrom.module, "__future__")) { + Py_DECREF(level); + Py_DECREF(names); + return compiler_error(c, "from __future__ imports must occur " + "at the beginning of the file"); + } + + ADDOP_O(c, LOAD_CONST, level, consts); + Py_DECREF(level); + ADDOP_O(c, LOAD_CONST, names, consts); + Py_DECREF(names); + if (s->v.ImportFrom.module) { + ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); + } + else { + ADDOP_NAME(c, IMPORT_NAME, empty_string, names); + } + for (i = 0; i < n; i++) { + alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); + identifier store_name; + + if (i == 0 && *PyUnicode_AS_UNICODE(alias->name) == '*') { + assert(n == 1); + ADDOP(c, IMPORT_STAR); + return 1; + } + + ADDOP_NAME(c, IMPORT_FROM, alias->name, names); + store_name = alias->name; + if (alias->asname) + store_name = alias->asname; + + if (!compiler_nameop(c, store_name, Store)) { + Py_DECREF(names); + return 0; + } + } + /* remove imported module */ + ADDOP(c, POP_TOP); + return 1; } static int compiler_assert(struct compiler *c, stmt_ty s) { - static PyObject *assertion_error = NULL; - basicblock *end; - - if (Py_OptimizeFlag) - return 1; - if (assertion_error == NULL) { - assertion_error = PyUnicode_InternFromString("AssertionError"); - if (assertion_error == NULL) - return 0; - } - 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) - return 0; - } - VISIT(c, expr, s->v.Assert.test); - end = compiler_new_block(c); - if (end == NULL) - return 0; - ADDOP_JABS(c, POP_JUMP_IF_TRUE, end); - ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); - if (s->v.Assert.msg) { - VISIT(c, expr, s->v.Assert.msg); - ADDOP_I(c, CALL_FUNCTION, 1); - } - ADDOP_I(c, RAISE_VARARGS, 1); - compiler_use_next_block(c, end); - return 1; + static PyObject *assertion_error = NULL; + basicblock *end; + + if (Py_OptimizeFlag) + return 1; + if (assertion_error == NULL) { + assertion_error = PyUnicode_InternFromString("AssertionError"); + if (assertion_error == NULL) + return 0; + } + 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) + return 0; + } + VISIT(c, expr, s->v.Assert.test); + end = compiler_new_block(c); + if (end == NULL) + return 0; + ADDOP_JABS(c, POP_JUMP_IF_TRUE, end); + ADDOP_O(c, LOAD_GLOBAL, assertion_error, names); + if (s->v.Assert.msg) { + VISIT(c, expr, s->v.Assert.msg); + ADDOP_I(c, CALL_FUNCTION, 1); + } + ADDOP_I(c, RAISE_VARARGS, 1); + compiler_use_next_block(c, end); + return 1; } static int compiler_visit_stmt(struct compiler *c, stmt_ty s) { - int i, n; - - /* Always assign a lineno to the next instruction for a stmt. */ - c->u->u_lineno = s->lineno; - c->u->u_lineno_set = 0; - - switch (s->kind) { - case FunctionDef_kind: - return compiler_function(c, s); - case ClassDef_kind: - return compiler_class(c, s); - case Return_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'return' outside function"); - if (s->v.Return.value) { - VISIT(c, expr, s->v.Return.value); - } - else - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, RETURN_VALUE); - break; - case Delete_kind: - VISIT_SEQ(c, expr, s->v.Delete.targets) - break; - case Assign_kind: - n = asdl_seq_LEN(s->v.Assign.targets); - VISIT(c, expr, s->v.Assign.value); - for (i = 0; i < n; i++) { - if (i < n - 1) - ADDOP(c, DUP_TOP); - VISIT(c, expr, - (expr_ty)asdl_seq_GET(s->v.Assign.targets, i)); - } - break; - case AugAssign_kind: - return compiler_augassign(c, s); - case For_kind: - return compiler_for(c, s); - case While_kind: - return compiler_while(c, s); - case If_kind: - return compiler_if(c, s); - case Raise_kind: - n = 0; - if (s->v.Raise.exc) { - VISIT(c, expr, s->v.Raise.exc); - n++; - if (s->v.Raise.cause) { - VISIT(c, expr, s->v.Raise.cause); - n++; - } - } - ADDOP_I(c, RAISE_VARARGS, n); - break; - case TryExcept_kind: - return compiler_try_except(c, s); - case TryFinally_kind: - return compiler_try_finally(c, s); - case Assert_kind: - return compiler_assert(c, s); - case Import_kind: - return compiler_import(c, s); - case ImportFrom_kind: - return compiler_from_import(c, s); - case Global_kind: - 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; - case Pass_kind: - break; - case Break_kind: - if (!compiler_in_loop(c)) - return compiler_error(c, "'break' outside loop"); - ADDOP(c, BREAK_LOOP); - break; - case Continue_kind: - return compiler_continue(c); - case With_kind: - return compiler_with(c, s); - } - return 1; + int i, n; + + /* Always assign a lineno to the next instruction for a stmt. */ + c->u->u_lineno = s->lineno; + c->u->u_lineno_set = 0; + + switch (s->kind) { + case FunctionDef_kind: + return compiler_function(c, s); + case ClassDef_kind: + return compiler_class(c, s); + case Return_kind: + if (c->u->u_ste->ste_type != FunctionBlock) + return compiler_error(c, "'return' outside function"); + if (s->v.Return.value) { + VISIT(c, expr, s->v.Return.value); + } + else + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, RETURN_VALUE); + break; + case Delete_kind: + VISIT_SEQ(c, expr, s->v.Delete.targets) + break; + case Assign_kind: + n = asdl_seq_LEN(s->v.Assign.targets); + VISIT(c, expr, s->v.Assign.value); + for (i = 0; i < n; i++) { + if (i < n - 1) + ADDOP(c, DUP_TOP); + VISIT(c, expr, + (expr_ty)asdl_seq_GET(s->v.Assign.targets, i)); + } + break; + case AugAssign_kind: + return compiler_augassign(c, s); + case For_kind: + return compiler_for(c, s); + case While_kind: + return compiler_while(c, s); + case If_kind: + return compiler_if(c, s); + case Raise_kind: + n = 0; + if (s->v.Raise.exc) { + VISIT(c, expr, s->v.Raise.exc); + n++; + if (s->v.Raise.cause) { + VISIT(c, expr, s->v.Raise.cause); + n++; + } + } + ADDOP_I(c, RAISE_VARARGS, n); + break; + case TryExcept_kind: + return compiler_try_except(c, s); + case TryFinally_kind: + return compiler_try_finally(c, s); + case Assert_kind: + return compiler_assert(c, s); + case Import_kind: + return compiler_import(c, s); + case ImportFrom_kind: + return compiler_from_import(c, s); + case Global_kind: + 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; + case Pass_kind: + break; + case Break_kind: + if (!compiler_in_loop(c)) + return compiler_error(c, "'break' outside loop"); + ADDOP(c, BREAK_LOOP); + break; + case Continue_kind: + return compiler_continue(c); + case With_kind: + return compiler_with(c, s); + } + return 1; } static int unaryop(unaryop_ty op) { - switch (op) { - case Invert: - return UNARY_INVERT; - case Not: - return UNARY_NOT; - case UAdd: - return UNARY_POSITIVE; - case USub: - return UNARY_NEGATIVE; - default: - PyErr_Format(PyExc_SystemError, - "unary op %d should not be possible", op); - return 0; - } + switch (op) { + case Invert: + return UNARY_INVERT; + case Not: + return UNARY_NOT; + case UAdd: + return UNARY_POSITIVE; + case USub: + return UNARY_NEGATIVE; + default: + PyErr_Format(PyExc_SystemError, + "unary op %d should not be possible", op); + return 0; + } } static int binop(struct compiler *c, operator_ty op) { - switch (op) { - case Add: - return BINARY_ADD; - case Sub: - return BINARY_SUBTRACT; - case Mult: - return BINARY_MULTIPLY; - case Div: - return BINARY_TRUE_DIVIDE; - case Mod: - return BINARY_MODULO; - case Pow: - return BINARY_POWER; - case LShift: - return BINARY_LSHIFT; - case RShift: - return BINARY_RSHIFT; - case BitOr: - return BINARY_OR; - case BitXor: - return BINARY_XOR; - case BitAnd: - return BINARY_AND; - case FloorDiv: - return BINARY_FLOOR_DIVIDE; - default: - PyErr_Format(PyExc_SystemError, - "binary op %d should not be possible", op); - return 0; - } + switch (op) { + case Add: + return BINARY_ADD; + case Sub: + return BINARY_SUBTRACT; + case Mult: + return BINARY_MULTIPLY; + case Div: + return BINARY_TRUE_DIVIDE; + case Mod: + return BINARY_MODULO; + case Pow: + return BINARY_POWER; + case LShift: + return BINARY_LSHIFT; + case RShift: + return BINARY_RSHIFT; + case BitOr: + return BINARY_OR; + case BitXor: + return BINARY_XOR; + case BitAnd: + return BINARY_AND; + case FloorDiv: + return BINARY_FLOOR_DIVIDE; + default: + PyErr_Format(PyExc_SystemError, + "binary op %d should not be possible", op); + return 0; + } } static int cmpop(cmpop_ty op) { - switch (op) { - case Eq: - return PyCmp_EQ; - case NotEq: - return PyCmp_NE; - case Lt: - return PyCmp_LT; - case LtE: - return PyCmp_LE; - case Gt: - return PyCmp_GT; - case GtE: - return PyCmp_GE; - case Is: - return PyCmp_IS; - case IsNot: - return PyCmp_IS_NOT; - case In: - return PyCmp_IN; - case NotIn: - return PyCmp_NOT_IN; - default: - return PyCmp_BAD; - } + switch (op) { + case Eq: + return PyCmp_EQ; + case NotEq: + return PyCmp_NE; + case Lt: + return PyCmp_LT; + case LtE: + return PyCmp_LE; + case Gt: + return PyCmp_GT; + case GtE: + return PyCmp_GE; + case Is: + return PyCmp_IS; + case IsNot: + return PyCmp_IS_NOT; + case In: + return PyCmp_IN; + case NotIn: + return PyCmp_NOT_IN; + default: + return PyCmp_BAD; + } } static int inplace_binop(struct compiler *c, operator_ty op) { - switch (op) { - case Add: - return INPLACE_ADD; - case Sub: - return INPLACE_SUBTRACT; - case Mult: - return INPLACE_MULTIPLY; - case Div: - return INPLACE_TRUE_DIVIDE; - case Mod: - return INPLACE_MODULO; - case Pow: - return INPLACE_POWER; - case LShift: - return INPLACE_LSHIFT; - case RShift: - return INPLACE_RSHIFT; - case BitOr: - return INPLACE_OR; - case BitXor: - return INPLACE_XOR; - case BitAnd: - return INPLACE_AND; - case FloorDiv: - return INPLACE_FLOOR_DIVIDE; - default: - PyErr_Format(PyExc_SystemError, - "inplace binary op %d should not be possible", op); - return 0; - } + switch (op) { + case Add: + return INPLACE_ADD; + case Sub: + return INPLACE_SUBTRACT; + case Mult: + return INPLACE_MULTIPLY; + case Div: + return INPLACE_TRUE_DIVIDE; + case Mod: + return INPLACE_MODULO; + case Pow: + return INPLACE_POWER; + case LShift: + return INPLACE_LSHIFT; + case RShift: + return INPLACE_RSHIFT; + case BitOr: + return INPLACE_OR; + case BitXor: + return INPLACE_XOR; + case BitAnd: + return INPLACE_AND; + case FloorDiv: + return INPLACE_FLOOR_DIVIDE; + default: + PyErr_Format(PyExc_SystemError, + "inplace binary op %d should not be possible", op); + return 0; + } } static int compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) { - int op, scope, arg; - enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype; - - PyObject *dict = c->u->u_names; - PyObject *mangled; - /* XXX AugStore isn't used anywhere! */ - - mangled = _Py_Mangle(c->u->u_private, name); - if (!mangled) - return 0; - - op = 0; - optype = OP_NAME; - scope = PyST_GetScope(c->u->u_ste, mangled); - switch (scope) { - case FREE: - dict = c->u->u_freevars; - optype = OP_DEREF; - break; - case CELL: - dict = c->u->u_cellvars; - optype = OP_DEREF; - break; - case LOCAL: - if (c->u->u_ste->ste_type == FunctionBlock) - optype = OP_FAST; - break; - case GLOBAL_IMPLICIT: - if (c->u->u_ste->ste_type == FunctionBlock && - !c->u->u_ste->ste_unoptimized) - optype = OP_GLOBAL; - break; - case GLOBAL_EXPLICIT: - optype = OP_GLOBAL; - break; - default: - /* scope can be 0 */ - break; - } - - /* XXX Leave assert here, but handle __doc__ and the like better */ - assert(scope || PyUnicode_AS_UNICODE(name)[0] == '_'); - - switch (optype) { - case OP_DEREF: - switch (ctx) { - case Load: op = LOAD_DEREF; break; - case Store: op = STORE_DEREF; break; - case AugLoad: - case AugStore: - break; - case Del: - PyErr_Format(PyExc_SyntaxError, - "can not delete variable '%S' referenced " - "in nested scope", - name); - Py_DECREF(mangled); - return 0; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for deref variable"); - return 0; - } - break; - case OP_FAST: - switch (ctx) { - case Load: op = LOAD_FAST; break; - case Store: op = STORE_FAST; break; - case Del: op = DELETE_FAST; break; - case AugLoad: - case AugStore: - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for local variable"); - return 0; - } - ADDOP_O(c, op, mangled, varnames); - Py_DECREF(mangled); - return 1; - case OP_GLOBAL: - switch (ctx) { - case Load: op = LOAD_GLOBAL; break; - case Store: op = STORE_GLOBAL; break; - case Del: op = DELETE_GLOBAL; break; - case AugLoad: - case AugStore: - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for global variable"); - return 0; - } - break; - case OP_NAME: - switch (ctx) { - case Load: op = LOAD_NAME; break; - case Store: op = STORE_NAME; break; - case Del: op = DELETE_NAME; break; - case AugLoad: - case AugStore: - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid for name variable"); - return 0; - } - break; - } - - assert(op); - arg = compiler_add_o(c, dict, mangled); - Py_DECREF(mangled); - if (arg < 0) - return 0; - return compiler_addop_i(c, op, arg); + int op, scope, arg; + enum { OP_FAST, OP_GLOBAL, OP_DEREF, OP_NAME } optype; + + PyObject *dict = c->u->u_names; + PyObject *mangled; + /* XXX AugStore isn't used anywhere! */ + + mangled = _Py_Mangle(c->u->u_private, name); + if (!mangled) + return 0; + + op = 0; + optype = OP_NAME; + scope = PyST_GetScope(c->u->u_ste, mangled); + switch (scope) { + case FREE: + dict = c->u->u_freevars; + optype = OP_DEREF; + break; + case CELL: + dict = c->u->u_cellvars; + optype = OP_DEREF; + break; + case LOCAL: + if (c->u->u_ste->ste_type == FunctionBlock) + optype = OP_FAST; + break; + case GLOBAL_IMPLICIT: + if (c->u->u_ste->ste_type == FunctionBlock && + !c->u->u_ste->ste_unoptimized) + optype = OP_GLOBAL; + break; + case GLOBAL_EXPLICIT: + optype = OP_GLOBAL; + break; + default: + /* scope can be 0 */ + break; + } + + /* XXX Leave assert here, but handle __doc__ and the like better */ + assert(scope || PyUnicode_AS_UNICODE(name)[0] == '_'); + + switch (optype) { + case OP_DEREF: + switch (ctx) { + case Load: op = LOAD_DEREF; break; + case Store: op = STORE_DEREF; break; + case AugLoad: + case AugStore: + break; + case Del: + PyErr_Format(PyExc_SyntaxError, + "can not delete variable '%S' referenced " + "in nested scope", + name); + Py_DECREF(mangled); + return 0; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid for deref variable"); + return 0; + } + break; + case OP_FAST: + switch (ctx) { + case Load: op = LOAD_FAST; break; + case Store: op = STORE_FAST; break; + case Del: op = DELETE_FAST; break; + case AugLoad: + case AugStore: + break; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid for local variable"); + return 0; + } + ADDOP_O(c, op, mangled, varnames); + Py_DECREF(mangled); + return 1; + case OP_GLOBAL: + switch (ctx) { + case Load: op = LOAD_GLOBAL; break; + case Store: op = STORE_GLOBAL; break; + case Del: op = DELETE_GLOBAL; break; + case AugLoad: + case AugStore: + break; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid for global variable"); + return 0; + } + break; + case OP_NAME: + switch (ctx) { + case Load: op = LOAD_NAME; break; + case Store: op = STORE_NAME; break; + case Del: op = DELETE_NAME; break; + case AugLoad: + case AugStore: + break; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid for name variable"); + return 0; + } + break; + } + + assert(op); + arg = compiler_add_o(c, dict, mangled); + Py_DECREF(mangled); + if (arg < 0) + return 0; + return compiler_addop_i(c, op, arg); } static int compiler_boolop(struct compiler *c, expr_ty e) { - basicblock *end; - int jumpi, i, n; - asdl_seq *s; - - assert(e->kind == BoolOp_kind); - if (e->v.BoolOp.op == And) - jumpi = JUMP_IF_FALSE_OR_POP; - else - jumpi = JUMP_IF_TRUE_OR_POP; - end = compiler_new_block(c); - if (end == NULL) - return 0; - s = e->v.BoolOp.values; - n = asdl_seq_LEN(s) - 1; - assert(n >= 0); - for (i = 0; i < n; ++i) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); - ADDOP_JABS(c, jumpi, end); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); - compiler_use_next_block(c, end); - return 1; + basicblock *end; + int jumpi, i, n; + asdl_seq *s; + + assert(e->kind == BoolOp_kind); + if (e->v.BoolOp.op == And) + jumpi = JUMP_IF_FALSE_OR_POP; + else + jumpi = JUMP_IF_TRUE_OR_POP; + end = compiler_new_block(c); + if (end == NULL) + return 0; + s = e->v.BoolOp.values; + n = asdl_seq_LEN(s) - 1; + assert(n >= 0); + for (i = 0; i < n; ++i) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); + ADDOP_JABS(c, jumpi, end); + } + VISIT(c, expr, (expr_ty)asdl_seq_GET(s, n)); + compiler_use_next_block(c, end); + return 1; } static int compiler_list(struct compiler *c, expr_ty e) { - int 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"); - } - } - if (!seen_star) { - ADDOP_I(c, UNPACK_SEQUENCE, n); - } - } - VISIT_SEQ(c, expr, e->v.List.elts); - if (e->v.List.ctx == Load) { - ADDOP_I(c, BUILD_LIST, n); - } - return 1; + int 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"); + } + } + if (!seen_star) { + ADDOP_I(c, UNPACK_SEQUENCE, n); + } + } + VISIT_SEQ(c, expr, e->v.List.elts); + if (e->v.List.ctx == Load) { + ADDOP_I(c, BUILD_LIST, n); + } + return 1; } static int compiler_tuple(struct compiler *c, expr_ty e) { - int n = asdl_seq_LEN(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"); - } - } - if (!seen_star) { - ADDOP_I(c, UNPACK_SEQUENCE, n); - } - } - VISIT_SEQ(c, expr, e->v.Tuple.elts); - if (e->v.Tuple.ctx == Load) { - ADDOP_I(c, BUILD_TUPLE, n); - } - return 1; + int n = asdl_seq_LEN(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"); + } + } + if (!seen_star) { + ADDOP_I(c, UNPACK_SEQUENCE, n); + } + } + VISIT_SEQ(c, expr, e->v.Tuple.elts); + if (e->v.Tuple.ctx == Load) { + ADDOP_I(c, BUILD_TUPLE, n); + } + return 1; } static int compiler_compare(struct compiler *c, expr_ty e) { - int i, n; - basicblock *cleanup = NULL; - - /* XXX the logic can be cleaned up for 1 or multiple comparisons */ - VISIT(c, expr, e->v.Compare.left); - n = asdl_seq_LEN(e->v.Compare.ops); - assert(n > 0); - if (n > 1) { - cleanup = compiler_new_block(c); - if (cleanup == NULL) - return 0; - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); - } - for (i = 1; i < n; i++) { - ADDOP(c, DUP_TOP); - ADDOP(c, ROT_THREE); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET( - e->v.Compare.ops, i - 1)))); - ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); - NEXT_BLOCK(c); - if (i < (n - 1)) - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n - 1)); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n - 1)))); - if (n > 1) { - basicblock *end = compiler_new_block(c); - if (end == NULL) - return 0; - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, cleanup); - ADDOP(c, ROT_TWO); - ADDOP(c, POP_TOP); - compiler_use_next_block(c, end); - } - return 1; + int i, n; + basicblock *cleanup = NULL; + + /* XXX the logic can be cleaned up for 1 or multiple comparisons */ + VISIT(c, expr, e->v.Compare.left); + n = asdl_seq_LEN(e->v.Compare.ops); + assert(n > 0); + if (n > 1) { + cleanup = compiler_new_block(c); + if (cleanup == NULL) + return 0; + VISIT(c, expr, + (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); + } + for (i = 1; i < n; i++) { + ADDOP(c, DUP_TOP); + ADDOP(c, ROT_THREE); + ADDOP_I(c, COMPARE_OP, + cmpop((cmpop_ty)(asdl_seq_GET( + e->v.Compare.ops, i - 1)))); + ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); + NEXT_BLOCK(c); + if (i < (n - 1)) + VISIT(c, expr, + (expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); + } + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n - 1)); + ADDOP_I(c, COMPARE_OP, + cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n - 1)))); + if (n > 1) { + basicblock *end = compiler_new_block(c); + if (end == NULL) + return 0; + ADDOP_JREL(c, JUMP_FORWARD, end); + compiler_use_next_block(c, cleanup); + ADDOP(c, ROT_TWO); + ADDOP(c, POP_TOP); + compiler_use_next_block(c, end); + } + return 1; } static int 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); + 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); } /* shared code between compiler_call and compiler_class */ static int compiler_call_helper(struct compiler *c, - int n, /* Args already pushed */ - asdl_seq *args, - asdl_seq *keywords, - expr_ty starargs, - expr_ty kwargs) -{ - 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; - } - if (starargs) { - VISIT(c, expr, starargs); - code |= 1; - } - if (kwargs) { - VISIT(c, expr, kwargs); - code |= 2; - } - switch (code) { - case 0: - ADDOP_I(c, CALL_FUNCTION, n); - break; - case 1: - ADDOP_I(c, CALL_FUNCTION_VAR, n); - break; - case 2: - ADDOP_I(c, CALL_FUNCTION_KW, n); - break; - case 3: - ADDOP_I(c, CALL_FUNCTION_VAR_KW, n); - break; - } - return 1; + int n, /* Args already pushed */ + asdl_seq *args, + asdl_seq *keywords, + expr_ty starargs, + expr_ty kwargs) +{ + 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; + } + if (starargs) { + VISIT(c, expr, starargs); + code |= 1; + } + if (kwargs) { + VISIT(c, expr, kwargs); + code |= 2; + } + switch (code) { + case 0: + ADDOP_I(c, CALL_FUNCTION, n); + break; + case 1: + ADDOP_I(c, CALL_FUNCTION_VAR, n); + break; + case 2: + ADDOP_I(c, CALL_FUNCTION_KW, n); + break; + case 3: + ADDOP_I(c, CALL_FUNCTION_VAR_KW, n); + break; + } + return 1; } @@ -2787,228 +2787,228 @@ compiler_call_helper(struct compiler *c, */ static int -compiler_comprehension_generator(struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type) -{ - /* generate code for the iterator, then each of the ifs, - and then write to the element */ - - comprehension_ty gen; - basicblock *start, *anchor, *skip, *if_cleanup; - int i, n; - - start = compiler_new_block(c); - skip = compiler_new_block(c); - if_cleanup = compiler_new_block(c); - anchor = compiler_new_block(c); - - if (start == NULL || skip == NULL || if_cleanup == NULL || - anchor == NULL) - return 0; - - gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); - - if (gen_index == 0) { - /* Receive outermost iter as an implicit argument */ - c->u->u_argcount = 1; - ADDOP_I(c, LOAD_FAST, 0); - } - else { - /* Sub-iter - calculate on the fly */ - VISIT(c, expr, gen->iter); - ADDOP(c, GET_ITER); - } - compiler_use_next_block(c, start); - ADDOP_JREL(c, FOR_ITER, anchor); - NEXT_BLOCK(c); - VISIT(c, expr, gen->target); - - /* XXX this needs to be cleaned up...a lot! */ - n = asdl_seq_LEN(gen->ifs); - for (i = 0; i < n; i++) { - expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i); - VISIT(c, expr, e); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); - NEXT_BLOCK(c); - } - - if (++gen_index < asdl_seq_LEN(generators)) - if (!compiler_comprehension_generator(c, - generators, gen_index, - elt, val, type)) - return 0; - - /* only append after the last for generator */ - if (gen_index >= asdl_seq_LEN(generators)) { - /* comprehension specific code */ - switch (type) { - case COMP_GENEXP: - VISIT(c, expr, elt); - ADDOP(c, YIELD_VALUE); - ADDOP(c, POP_TOP); - break; - case COMP_LISTCOMP: - VISIT(c, expr, elt); - ADDOP_I(c, LIST_APPEND, gen_index + 1); - break; - case COMP_SETCOMP: - VISIT(c, expr, elt); - ADDOP_I(c, SET_ADD, gen_index + 1); - break; - case COMP_DICTCOMP: - /* With 'd[k] = v', v is evaluated before k, so we do - the same. */ - VISIT(c, expr, val); - VISIT(c, expr, elt); - ADDOP_I(c, MAP_ADD, gen_index + 1); - break; - default: - return 0; - } - - compiler_use_next_block(c, skip); - } - compiler_use_next_block(c, if_cleanup); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - compiler_use_next_block(c, anchor); - - return 1; +compiler_comprehension_generator(struct compiler *c, + asdl_seq *generators, int gen_index, + expr_ty elt, expr_ty val, int type) +{ + /* generate code for the iterator, then each of the ifs, + and then write to the element */ + + comprehension_ty gen; + basicblock *start, *anchor, *skip, *if_cleanup; + int i, n; + + start = compiler_new_block(c); + skip = compiler_new_block(c); + if_cleanup = compiler_new_block(c); + anchor = compiler_new_block(c); + + if (start == NULL || skip == NULL || if_cleanup == NULL || + anchor == NULL) + return 0; + + gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); + + if (gen_index == 0) { + /* Receive outermost iter as an implicit argument */ + c->u->u_argcount = 1; + ADDOP_I(c, LOAD_FAST, 0); + } + else { + /* Sub-iter - calculate on the fly */ + VISIT(c, expr, gen->iter); + ADDOP(c, GET_ITER); + } + compiler_use_next_block(c, start); + ADDOP_JREL(c, FOR_ITER, anchor); + NEXT_BLOCK(c); + VISIT(c, expr, gen->target); + + /* XXX this needs to be cleaned up...a lot! */ + n = asdl_seq_LEN(gen->ifs); + for (i = 0; i < n; i++) { + expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i); + VISIT(c, expr, e); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); + NEXT_BLOCK(c); + } + + if (++gen_index < asdl_seq_LEN(generators)) + if (!compiler_comprehension_generator(c, + generators, gen_index, + elt, val, type)) + return 0; + + /* only append after the last for generator */ + if (gen_index >= asdl_seq_LEN(generators)) { + /* comprehension specific code */ + switch (type) { + case COMP_GENEXP: + VISIT(c, expr, elt); + ADDOP(c, YIELD_VALUE); + ADDOP(c, POP_TOP); + break; + case COMP_LISTCOMP: + VISIT(c, expr, elt); + ADDOP_I(c, LIST_APPEND, gen_index + 1); + break; + case COMP_SETCOMP: + VISIT(c, expr, elt); + ADDOP_I(c, SET_ADD, gen_index + 1); + break; + case COMP_DICTCOMP: + /* With 'd[k] = v', v is evaluated before k, so we do + the same. */ + VISIT(c, expr, val); + VISIT(c, expr, elt); + ADDOP_I(c, MAP_ADD, gen_index + 1); + break; + default: + return 0; + } + + compiler_use_next_block(c, skip); + } + compiler_use_next_block(c, if_cleanup); + ADDOP_JABS(c, JUMP_ABSOLUTE, start); + compiler_use_next_block(c, anchor); + + return 1; } static int 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; - - outermost_iter = ((comprehension_ty) - asdl_seq_GET(generators, 0))->iter; - - if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) - goto error; - - if (type != COMP_GENEXP) { - int op; - switch (type) { - case COMP_LISTCOMP: - op = BUILD_LIST; - break; - case COMP_SETCOMP: - op = BUILD_SET; - break; - case COMP_DICTCOMP: - op = BUILD_MAP; - break; - default: - PyErr_Format(PyExc_SystemError, - "unknown comprehension type %d", type); - goto error_in_scope; - } - - ADDOP_I(c, op, 0); - } - - if (!compiler_comprehension_generator(c, generators, 0, elt, - val, type)) - goto error_in_scope; - - if (type != COMP_GENEXP) { - ADDOP(c, RETURN_VALUE); - } - - co = assemble(c, 1); - compiler_exit_scope(c); - if (co == NULL) - goto error; - - if (!compiler_make_closure(c, co, 0)) - goto error; - Py_DECREF(co); - - VISIT(c, expr, outermost_iter); - ADDOP(c, GET_ITER); - ADDOP_I(c, CALL_FUNCTION, 1); - return 1; + asdl_seq *generators, expr_ty elt, expr_ty val) +{ + PyCodeObject *co = NULL; + expr_ty outermost_iter; + + outermost_iter = ((comprehension_ty) + asdl_seq_GET(generators, 0))->iter; + + if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) + goto error; + + if (type != COMP_GENEXP) { + int op; + switch (type) { + case COMP_LISTCOMP: + op = BUILD_LIST; + break; + case COMP_SETCOMP: + op = BUILD_SET; + break; + case COMP_DICTCOMP: + op = BUILD_MAP; + break; + default: + PyErr_Format(PyExc_SystemError, + "unknown comprehension type %d", type); + goto error_in_scope; + } + + ADDOP_I(c, op, 0); + } + + if (!compiler_comprehension_generator(c, generators, 0, elt, + val, type)) + goto error_in_scope; + + if (type != COMP_GENEXP) { + ADDOP(c, RETURN_VALUE); + } + + co = assemble(c, 1); + compiler_exit_scope(c); + if (co == NULL) + goto error; + + if (!compiler_make_closure(c, co, 0)) + goto error; + Py_DECREF(co); + + VISIT(c, expr, outermost_iter); + ADDOP(c, GET_ITER); + ADDOP_I(c, CALL_FUNCTION, 1); + return 1; error_in_scope: - compiler_exit_scope(c); + compiler_exit_scope(c); error: - Py_XDECREF(co); - return 0; + Py_XDECREF(co); + return 0; } static int compiler_genexp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == GeneratorExp_kind); - return compiler_comprehension(c, e, COMP_GENEXP, name, - e->v.GeneratorExp.generators, - e->v.GeneratorExp.elt, NULL); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == GeneratorExp_kind); + return compiler_comprehension(c, e, COMP_GENEXP, name, + e->v.GeneratorExp.generators, + e->v.GeneratorExp.elt, NULL); } static int compiler_listcomp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == ListComp_kind); - return compiler_comprehension(c, e, COMP_LISTCOMP, name, - e->v.ListComp.generators, - e->v.ListComp.elt, NULL); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == ListComp_kind); + return compiler_comprehension(c, e, COMP_LISTCOMP, name, + e->v.ListComp.generators, + e->v.ListComp.elt, NULL); } static int compiler_setcomp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == SetComp_kind); - return compiler_comprehension(c, e, COMP_SETCOMP, name, - e->v.SetComp.generators, - e->v.SetComp.elt, NULL); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == SetComp_kind); + return compiler_comprehension(c, e, COMP_SETCOMP, name, + e->v.SetComp.generators, + e->v.SetComp.elt, NULL); } static int compiler_dictcomp(struct compiler *c, expr_ty e) { - static identifier name; - if (!name) { - name = PyUnicode_FromString(""); - if (!name) - return 0; - } - assert(e->kind == DictComp_kind); - return compiler_comprehension(c, e, COMP_DICTCOMP, name, - e->v.DictComp.generators, - e->v.DictComp.key, e->v.DictComp.value); + static identifier name; + if (!name) { + name = PyUnicode_FromString(""); + if (!name) + return 0; + } + assert(e->kind == DictComp_kind); + return compiler_comprehension(c, e, COMP_DICTCOMP, name, + e->v.DictComp.generators, + e->v.DictComp.key, e->v.DictComp.value); } static int compiler_visit_keyword(struct compiler *c, keyword_ty k) { - ADDOP_O(c, LOAD_CONST, k->arg, consts); - VISIT(c, expr, k->value); - return 1; + ADDOP_O(c, LOAD_CONST, k->arg, consts); + VISIT(c, expr, k->value); + return 1; } -/* Test whether expression is constant. For constants, report +/* Test whether expression is constant. For constants, report whether they are true or false. Return values: 1 for true, 0 for false, -1 for non-constant. @@ -3017,39 +3017,39 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(expr_ty e) { - char *id; - switch (e->kind) { - case Ellipsis_kind: - return 1; - case Num_kind: - return PyObject_IsTrue(e->v.Num.n); - case Str_kind: - return PyObject_IsTrue(e->v.Str.s); - case Name_kind: - /* optimize away names that can't be reassigned */ - id = PyBytes_AS_STRING( - _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL)); - 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 ! Py_OptimizeFlag; - /* fall through */ - default: - return -1; - } + char *id; + switch (e->kind) { + case Ellipsis_kind: + return 1; + case Num_kind: + return PyObject_IsTrue(e->v.Num.n); + case Str_kind: + return PyObject_IsTrue(e->v.Str.s); + case Name_kind: + /* optimize away names that can't be reassigned */ + id = PyBytes_AS_STRING( + _PyUnicode_AsDefaultEncodedString(e->v.Name.id, NULL)); + 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 ! Py_OptimizeFlag; + /* fall through */ + default: + return -1; + } } /* Implements the with statement from PEP 343. - The semantics outlined in that PEP are as follows: + The semantics outlined in that PEP are as follows: with EXPR as VAR: BLOCK - + It is implemented roughly as: - + context = EXPR exit = context.__exit__ # not calling it value = context.__enter__() @@ -3058,9 +3058,9 @@ expr_constant(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) exit(*exc) */ static int @@ -3073,7 +3073,7 @@ compiler_with(struct compiler *c, stmt_ty s) block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) - return 0; + return 0; /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); @@ -3082,15 +3082,15 @@ compiler_with(struct compiler *c, stmt_ty s) /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); if (!compiler_push_fblock(c, FINALLY_TRY, block)) { - return 0; + return 0; } if (s->v.With.optional_vars) { - VISIT(c, expr, s->v.With.optional_vars); + VISIT(c, expr, s->v.With.optional_vars); } else { - /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); + /* Discard result from context.__enter__() */ + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3103,7 +3103,7 @@ compiler_with(struct compiler *c, stmt_ty s) ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); if (!compiler_push_fblock(c, FINALLY_END, finally)) - return 0; + return 0; /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic @@ -3119,240 +3119,240 @@ compiler_with(struct compiler *c, stmt_ty s) static int compiler_visit_expr(struct compiler *c, expr_ty e) { - int i, n; - - /* If expr e has a different line number than the last expr/stmt, - set a new line number for the next instruction. - */ - if (e->lineno > c->u->u_lineno) { - c->u->u_lineno = e->lineno; - c->u->u_lineno_set = 0; - } - switch (e->kind) { - case BoolOp_kind: - return compiler_boolop(c, e); - case BinOp_kind: - VISIT(c, expr, e->v.BinOp.left); - VISIT(c, expr, e->v.BinOp.right); - ADDOP(c, binop(c, e->v.BinOp.op)); - break; - case UnaryOp_kind: - VISIT(c, expr, e->v.UnaryOp.operand); - ADDOP(c, unaryop(e->v.UnaryOp.op)); - break; - case Lambda_kind: - return compiler_lambda(c, e); - case IfExp_kind: - return compiler_ifexp(c, e); - case Dict_kind: - n = asdl_seq_LEN(e->v.Dict.values); - 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; - 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; - case GeneratorExp_kind: - return compiler_genexp(c, e); - case ListComp_kind: - return compiler_listcomp(c, e); - case SetComp_kind: - return compiler_setcomp(c, e); - case DictComp_kind: - return compiler_dictcomp(c, e); - case Yield_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'yield' outside function"); - if (e->v.Yield.value) { - VISIT(c, expr, e->v.Yield.value); - } - else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - ADDOP(c, YIELD_VALUE); - break; - case Compare_kind: - return compiler_compare(c, e); - case Call_kind: - return compiler_call(c, e); - 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 Bytes_kind: - ADDOP_O(c, LOAD_CONST, e->v.Bytes.s, consts); - break; - case Ellipsis_kind: - ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); - break; - /* The following exprs can be assignment targets. */ - case Attribute_kind: - if (e->v.Attribute.ctx != AugStore) - VISIT(c, expr, e->v.Attribute.value); - switch (e->v.Attribute.ctx) { - case AugLoad: - ADDOP(c, DUP_TOP); - /* Fall through to load */ - case Load: - ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names); - break; - case AugStore: - ADDOP(c, ROT_TWO); - /* Fall through to save */ - case Store: - ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names); - break; - case Del: - ADDOP_NAME(c, DELETE_ATTR, e->v.Attribute.attr, names); - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid in attribute expression"); - return 0; - } - break; - case Subscript_kind: - switch (e->v.Subscript.ctx) { - case AugLoad: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, AugLoad); - break; - case Load: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, Load); - break; - case AugStore: - VISIT_SLICE(c, e->v.Subscript.slice, AugStore); - break; - case Store: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, Store); - break; - case Del: - VISIT(c, expr, e->v.Subscript.value); - VISIT_SLICE(c, e->v.Subscript.slice, Del); - break; - case Param: - default: - PyErr_SetString(PyExc_SystemError, - "param invalid in subscript expression"); - return 0; - } - break; - case Starred_kind: - switch (e->v.Starred.ctx) { - case Store: - /* In all legitimate cases, the Starred node was already replaced - * by compiler_list/compiler_tuple. XXX: is that okay? */ - return compiler_error(c, - "starred assignment target must be in a list or tuple"); - default: - return compiler_error(c, - "can use starred expression only as assignment target"); - } - break; - case Name_kind: - return compiler_nameop(c, e->v.Name.id, e->v.Name.ctx); - /* child nodes of List and Tuple will have expr_context set */ - case List_kind: - return compiler_list(c, e); - case Tuple_kind: - return compiler_tuple(c, e); - } - return 1; + int i, n; + + /* If expr e has a different line number than the last expr/stmt, + set a new line number for the next instruction. + */ + if (e->lineno > c->u->u_lineno) { + c->u->u_lineno = e->lineno; + c->u->u_lineno_set = 0; + } + switch (e->kind) { + case BoolOp_kind: + return compiler_boolop(c, e); + case BinOp_kind: + VISIT(c, expr, e->v.BinOp.left); + VISIT(c, expr, e->v.BinOp.right); + ADDOP(c, binop(c, e->v.BinOp.op)); + break; + case UnaryOp_kind: + VISIT(c, expr, e->v.UnaryOp.operand); + ADDOP(c, unaryop(e->v.UnaryOp.op)); + break; + case Lambda_kind: + return compiler_lambda(c, e); + case IfExp_kind: + return compiler_ifexp(c, e); + case Dict_kind: + n = asdl_seq_LEN(e->v.Dict.values); + 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; + 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; + case GeneratorExp_kind: + return compiler_genexp(c, e); + case ListComp_kind: + return compiler_listcomp(c, e); + case SetComp_kind: + return compiler_setcomp(c, e); + case DictComp_kind: + return compiler_dictcomp(c, e); + case Yield_kind: + if (c->u->u_ste->ste_type != FunctionBlock) + return compiler_error(c, "'yield' outside function"); + if (e->v.Yield.value) { + VISIT(c, expr, e->v.Yield.value); + } + else { + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } + ADDOP(c, YIELD_VALUE); + break; + case Compare_kind: + return compiler_compare(c, e); + case Call_kind: + return compiler_call(c, e); + 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 Bytes_kind: + ADDOP_O(c, LOAD_CONST, e->v.Bytes.s, consts); + break; + case Ellipsis_kind: + ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); + break; + /* The following exprs can be assignment targets. */ + case Attribute_kind: + if (e->v.Attribute.ctx != AugStore) + VISIT(c, expr, e->v.Attribute.value); + switch (e->v.Attribute.ctx) { + case AugLoad: + ADDOP(c, DUP_TOP); + /* Fall through to load */ + case Load: + ADDOP_NAME(c, LOAD_ATTR, e->v.Attribute.attr, names); + break; + case AugStore: + ADDOP(c, ROT_TWO); + /* Fall through to save */ + case Store: + ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names); + break; + case Del: + ADDOP_NAME(c, DELETE_ATTR, e->v.Attribute.attr, names); + break; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid in attribute expression"); + return 0; + } + break; + case Subscript_kind: + switch (e->v.Subscript.ctx) { + case AugLoad: + VISIT(c, expr, e->v.Subscript.value); + VISIT_SLICE(c, e->v.Subscript.slice, AugLoad); + break; + case Load: + VISIT(c, expr, e->v.Subscript.value); + VISIT_SLICE(c, e->v.Subscript.slice, Load); + break; + case AugStore: + VISIT_SLICE(c, e->v.Subscript.slice, AugStore); + break; + case Store: + VISIT(c, expr, e->v.Subscript.value); + VISIT_SLICE(c, e->v.Subscript.slice, Store); + break; + case Del: + VISIT(c, expr, e->v.Subscript.value); + VISIT_SLICE(c, e->v.Subscript.slice, Del); + break; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid in subscript expression"); + return 0; + } + break; + case Starred_kind: + switch (e->v.Starred.ctx) { + case Store: + /* In all legitimate cases, the Starred node was already replaced + * by compiler_list/compiler_tuple. XXX: is that okay? */ + return compiler_error(c, + "starred assignment target must be in a list or tuple"); + default: + return compiler_error(c, + "can use starred expression only as assignment target"); + } + break; + case Name_kind: + return compiler_nameop(c, e->v.Name.id, e->v.Name.ctx); + /* child nodes of List and Tuple will have expr_context set */ + case List_kind: + return compiler_list(c, e); + case Tuple_kind: + return compiler_tuple(c, e); + } + return 1; } static int compiler_augassign(struct compiler *c, stmt_ty s) { - expr_ty e = s->v.AugAssign.target; - expr_ty auge; - - assert(s->kind == AugAssign_kind); - - switch (e->kind) { - case Attribute_kind: - auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr, - AugLoad, e->lineno, e->col_offset, c->c_arena); - if (auge == NULL) - return 0; - VISIT(c, expr, auge); - VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); - auge->v.Attribute.ctx = AugStore; - VISIT(c, expr, auge); - break; - case Subscript_kind: - auge = Subscript(e->v.Subscript.value, e->v.Subscript.slice, - AugLoad, e->lineno, e->col_offset, c->c_arena); - if (auge == NULL) - return 0; - VISIT(c, expr, auge); - VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); - auge->v.Subscript.ctx = AugStore; - VISIT(c, expr, auge); - break; - case Name_kind: - if (!compiler_nameop(c, e->v.Name.id, Load)) - return 0; - VISIT(c, expr, s->v.AugAssign.value); - ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); - return compiler_nameop(c, e->v.Name.id, Store); - default: - PyErr_Format(PyExc_SystemError, - "invalid node type (%d) for augmented assignment", - e->kind); - return 0; - } - return 1; + expr_ty e = s->v.AugAssign.target; + expr_ty auge; + + assert(s->kind == AugAssign_kind); + + switch (e->kind) { + case Attribute_kind: + auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr, + AugLoad, e->lineno, e->col_offset, c->c_arena); + if (auge == NULL) + return 0; + VISIT(c, expr, auge); + VISIT(c, expr, s->v.AugAssign.value); + ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); + auge->v.Attribute.ctx = AugStore; + VISIT(c, expr, auge); + break; + case Subscript_kind: + auge = Subscript(e->v.Subscript.value, e->v.Subscript.slice, + AugLoad, e->lineno, e->col_offset, c->c_arena); + if (auge == NULL) + return 0; + VISIT(c, expr, auge); + VISIT(c, expr, s->v.AugAssign.value); + ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); + auge->v.Subscript.ctx = AugStore; + VISIT(c, expr, auge); + break; + case Name_kind: + if (!compiler_nameop(c, e->v.Name.id, Load)) + return 0; + VISIT(c, expr, s->v.AugAssign.value); + ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); + return compiler_nameop(c, e->v.Name.id, Store); + default: + PyErr_Format(PyExc_SystemError, + "invalid node type (%d) for augmented assignment", + e->kind); + return 0; + } + return 1; } static int compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b) { - struct fblockinfo *f; - if (c->u->u_nfblocks >= CO_MAXBLOCKS) { - PyErr_SetString(PyExc_SystemError, - "too many statically nested blocks"); - return 0; - } - f = &c->u->u_fblock[c->u->u_nfblocks++]; - f->fb_type = t; - f->fb_block = b; - return 1; + struct fblockinfo *f; + if (c->u->u_nfblocks >= CO_MAXBLOCKS) { + PyErr_SetString(PyExc_SystemError, + "too many statically nested blocks"); + return 0; + } + f = &c->u->u_fblock[c->u->u_nfblocks++]; + f->fb_type = t; + f->fb_block = b; + return 1; } static void compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) { - struct compiler_unit *u = c->u; - assert(u->u_nfblocks > 0); - u->u_nfblocks--; - assert(u->u_fblock[u->u_nfblocks].fb_type == t); - assert(u->u_fblock[u->u_nfblocks].fb_block == b); + struct compiler_unit *u = c->u; + assert(u->u_nfblocks > 0); + u->u_nfblocks--; + assert(u->u_fblock[u->u_nfblocks].fb_type == t); + assert(u->u_fblock[u->u_nfblocks].fb_block == b); } static int compiler_in_loop(struct compiler *c) { - int i; - struct compiler_unit *u = c->u; - for (i = 0; i < u->u_nfblocks; ++i) { - if (u->u_fblock[i].fb_type == LOOP) - return 1; - } - return 0; + int i; + struct compiler_unit *u = c->u; + for (i = 0; i < u->u_nfblocks; ++i) { + if (u->u_fblock[i].fb_type == LOOP) + return 1; + } + return 0; } /* Raises a SyntaxError and returns 0. If something goes wrong, a different exception may be raised. @@ -3361,143 +3361,143 @@ compiler_in_loop(struct compiler *c) { static int 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); - if (!loc) { - Py_INCREF(Py_None); - loc = Py_None; - } - u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, - Py_None, loc); - if (!u) - goto exit; - v = Py_BuildValue("(zO)", errstr, u); - if (!v) - goto exit; - PyErr_SetObject(PyExc_SyntaxError, v); + PyObject *loc; + PyObject *u = NULL, *v = NULL; + + loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); + if (!loc) { + Py_INCREF(Py_None); + loc = Py_None; + } + u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, + Py_None, loc); + if (!u) + goto exit; + v = Py_BuildValue("(zO)", errstr, u); + if (!v) + goto exit; + PyErr_SetObject(PyExc_SyntaxError, v); exit: - Py_DECREF(loc); - Py_XDECREF(u); - Py_XDECREF(v); - return 0; -} - -static int -compiler_handle_subscr(struct compiler *c, const char *kind, - expr_context_ty ctx) -{ - int op = 0; - - /* XXX this code is duplicated */ - switch (ctx) { - case AugLoad: /* fall through to Load */ - case Load: op = BINARY_SUBSCR; break; - case AugStore:/* fall through to Store */ - case Store: op = STORE_SUBSCR; break; - case Del: op = DELETE_SUBSCR; break; - case Param: - PyErr_Format(PyExc_SystemError, - "invalid %s kind %d in subscript\n", - kind, ctx); - return 0; - } - if (ctx == AugLoad) { - ADDOP_I(c, DUP_TOPX, 2); - } - else if (ctx == AugStore) { - ADDOP(c, ROT_THREE); - } - ADDOP(c, op); - return 1; + Py_DECREF(loc); + Py_XDECREF(u); + Py_XDECREF(v); + return 0; +} + +static int +compiler_handle_subscr(struct compiler *c, const char *kind, + expr_context_ty ctx) +{ + int op = 0; + + /* XXX this code is duplicated */ + switch (ctx) { + case AugLoad: /* fall through to Load */ + case Load: op = BINARY_SUBSCR; break; + case AugStore:/* fall through to Store */ + case Store: op = STORE_SUBSCR; break; + case Del: op = DELETE_SUBSCR; break; + case Param: + PyErr_Format(PyExc_SystemError, + "invalid %s kind %d in subscript\n", + kind, ctx); + return 0; + } + if (ctx == AugLoad) { + ADDOP_I(c, DUP_TOPX, 2); + } + else if (ctx == AugStore) { + ADDOP(c, ROT_THREE); + } + ADDOP(c, op); + return 1; } static int compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) { - int n = 2; - assert(s->kind == Slice_kind); - - /* only handles the cases where BUILD_SLICE is emitted */ - if (s->v.Slice.lower) { - VISIT(c, expr, s->v.Slice.lower); - } - else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - - if (s->v.Slice.upper) { - VISIT(c, expr, s->v.Slice.upper); - } - else { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - - if (s->v.Slice.step) { - n++; - VISIT(c, expr, s->v.Slice.step); - } - ADDOP_I(c, BUILD_SLICE, n); - return 1; -} - -static int -compiler_visit_nested_slice(struct compiler *c, slice_ty s, - expr_context_ty ctx) -{ - switch (s->kind) { - case Slice_kind: - return compiler_slice(c, s, ctx); - case Index_kind: - VISIT(c, expr, s->v.Index.value); - break; - case ExtSlice_kind: - default: - PyErr_SetString(PyExc_SystemError, - "extended slice invalid in nested slice"); - return 0; - } - return 1; + int n = 2; + assert(s->kind == Slice_kind); + + /* only handles the cases where BUILD_SLICE is emitted */ + if (s->v.Slice.lower) { + VISIT(c, expr, s->v.Slice.lower); + } + else { + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } + + if (s->v.Slice.upper) { + VISIT(c, expr, s->v.Slice.upper); + } + else { + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } + + if (s->v.Slice.step) { + n++; + VISIT(c, expr, s->v.Slice.step); + } + ADDOP_I(c, BUILD_SLICE, n); + return 1; +} + +static int +compiler_visit_nested_slice(struct compiler *c, slice_ty s, + expr_context_ty ctx) +{ + switch (s->kind) { + case Slice_kind: + return compiler_slice(c, s, ctx); + case Index_kind: + VISIT(c, expr, s->v.Index.value); + break; + case ExtSlice_kind: + default: + PyErr_SetString(PyExc_SystemError, + "extended slice invalid in nested slice"); + return 0; + } + return 1; } static int compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) { - char * kindname = NULL; - switch (s->kind) { - case Index_kind: - kindname = "index"; - if (ctx != AugStore) { - VISIT(c, expr, s->v.Index.value); - } - break; - case Slice_kind: - kindname = "slice"; - if (ctx != AugStore) { - if (!compiler_slice(c, s, ctx)) - return 0; - } - break; - case ExtSlice_kind: - kindname = "extended slice"; - if (ctx != AugStore) { - int i, n = asdl_seq_LEN(s->v.ExtSlice.dims); - for (i = 0; i < n; i++) { - slice_ty sub = (slice_ty)asdl_seq_GET( - s->v.ExtSlice.dims, i); - if (!compiler_visit_nested_slice(c, sub, ctx)) - return 0; - } - ADDOP_I(c, BUILD_TUPLE, n); - } - break; - default: - PyErr_Format(PyExc_SystemError, - "invalid subscript kind %d", s->kind); - return 0; - } - return compiler_handle_subscr(c, kindname, ctx); + char * kindname = NULL; + switch (s->kind) { + case Index_kind: + kindname = "index"; + if (ctx != AugStore) { + VISIT(c, expr, s->v.Index.value); + } + break; + case Slice_kind: + kindname = "slice"; + if (ctx != AugStore) { + if (!compiler_slice(c, s, ctx)) + return 0; + } + break; + case ExtSlice_kind: + kindname = "extended slice"; + if (ctx != AugStore) { + int i, n = asdl_seq_LEN(s->v.ExtSlice.dims); + for (i = 0; i < n; i++) { + slice_ty sub = (slice_ty)asdl_seq_GET( + s->v.ExtSlice.dims, i); + if (!compiler_visit_nested_slice(c, sub, ctx)) + return 0; + } + ADDOP_I(c, BUILD_TUPLE, n); + } + break; + default: + PyErr_Format(PyExc_SystemError, + "invalid subscript kind %d", s->kind); + return 0; + } + return compiler_handle_subscr(c, kindname, ctx); } /* End of the compiler section, beginning of the assembler section */ @@ -3509,73 +3509,73 @@ compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) */ struct assembler { - PyObject *a_bytecode; /* string containing bytecode */ - int a_offset; /* offset into bytecode */ - int a_nblocks; /* number of reachable blocks */ - basicblock **a_postorder; /* list of blocks in dfs postorder */ - PyObject *a_lnotab; /* string containing lnotab */ - int a_lnotab_off; /* offset into lnotab */ - int a_lineno; /* last lineno of emitted instruction */ - int a_lineno_off; /* bytecode offset of last lineno */ + PyObject *a_bytecode; /* string containing bytecode */ + int a_offset; /* offset into bytecode */ + int a_nblocks; /* number of reachable blocks */ + basicblock **a_postorder; /* list of blocks in dfs postorder */ + PyObject *a_lnotab; /* string containing lnotab */ + int a_lnotab_off; /* offset into lnotab */ + int a_lineno; /* last lineno of emitted instruction */ + int a_lineno_off; /* bytecode offset of last lineno */ }; static void dfs(struct compiler *c, basicblock *b, struct assembler *a) { - int i; - struct instr *instr = NULL; - - if (b->b_seen) - return; - b->b_seen = 1; - if (b->b_next != NULL) - dfs(c, b->b_next, a); - for (i = 0; i < b->b_iused; i++) { - instr = &b->b_instr[i]; - if (instr->i_jrel || instr->i_jabs) - dfs(c, instr->i_target, a); - } - a->a_postorder[a->a_nblocks++] = b; + int i; + struct instr *instr = NULL; + + if (b->b_seen) + return; + b->b_seen = 1; + if (b->b_next != NULL) + dfs(c, b->b_next, a); + for (i = 0; i < b->b_iused; i++) { + instr = &b->b_instr[i]; + if (instr->i_jrel || instr->i_jabs) + dfs(c, instr->i_target, a); + } + a->a_postorder[a->a_nblocks++] = b; } static int stackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth) { - int i, target_depth; - struct instr *instr; - if (b->b_seen || b->b_startdepth >= depth) - return maxdepth; - b->b_seen = 1; - b->b_startdepth = depth; - for (i = 0; i < b->b_iused; i++) { - instr = &b->b_instr[i]; - depth += opcode_stack_effect(instr->i_opcode, instr->i_oparg); - if (depth > maxdepth) - maxdepth = depth; - assert(depth >= 0); /* invalid code or bug in stackdepth() */ - if (instr->i_jrel || instr->i_jabs) { - target_depth = depth; - if (instr->i_opcode == FOR_ITER) { - target_depth = depth-2; - } else if (instr->i_opcode == SETUP_FINALLY || - instr->i_opcode == SETUP_EXCEPT) { - target_depth = depth+3; - if (target_depth > maxdepth) - maxdepth = target_depth; - } - maxdepth = stackdepth_walk(c, instr->i_target, - target_depth, maxdepth); - if (instr->i_opcode == JUMP_ABSOLUTE || - instr->i_opcode == JUMP_FORWARD) { - goto out; /* remaining code is dead */ - } - } - } - if (b->b_next) - maxdepth = stackdepth_walk(c, b->b_next, depth, maxdepth); + int i, target_depth; + struct instr *instr; + if (b->b_seen || b->b_startdepth >= depth) + return maxdepth; + b->b_seen = 1; + b->b_startdepth = depth; + for (i = 0; i < b->b_iused; i++) { + instr = &b->b_instr[i]; + depth += opcode_stack_effect(instr->i_opcode, instr->i_oparg); + if (depth > maxdepth) + maxdepth = depth; + assert(depth >= 0); /* invalid code or bug in stackdepth() */ + if (instr->i_jrel || instr->i_jabs) { + target_depth = depth; + if (instr->i_opcode == FOR_ITER) { + target_depth = depth-2; + } else if (instr->i_opcode == SETUP_FINALLY || + instr->i_opcode == SETUP_EXCEPT) { + target_depth = depth+3; + if (target_depth > maxdepth) + maxdepth = target_depth; + } + maxdepth = stackdepth_walk(c, instr->i_target, + target_depth, maxdepth); + if (instr->i_opcode == JUMP_ABSOLUTE || + instr->i_opcode == JUMP_FORWARD) { + goto out; /* remaining code is dead */ + } + } + } + if (b->b_next) + maxdepth = stackdepth_walk(c, b->b_next, depth, maxdepth); out: - b->b_seen = 0; - return maxdepth; + b->b_seen = 0; + return maxdepth; } /* Find the flow path that needs the largest stack. We assume that @@ -3584,49 +3584,49 @@ out: static int stackdepth(struct compiler *c) { - basicblock *b, *entryblock; - entryblock = NULL; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - b->b_seen = 0; - b->b_startdepth = INT_MIN; - entryblock = b; - } - if (!entryblock) - return 0; - return stackdepth_walk(c, entryblock, 0, 0); + basicblock *b, *entryblock; + entryblock = NULL; + for (b = c->u->u_blocks; b != NULL; b = b->b_list) { + b->b_seen = 0; + b->b_startdepth = INT_MIN; + entryblock = b; + } + if (!entryblock) + return 0; + return stackdepth_walk(c, entryblock, 0, 0); } static int assemble_init(struct assembler *a, int nblocks, int firstlineno) { - memset(a, 0, sizeof(struct assembler)); - a->a_lineno = firstlineno; - a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE); - if (!a->a_bytecode) - return 0; - a->a_lnotab = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); - if (!a->a_lnotab) - return 0; - if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) { - PyErr_NoMemory(); - return 0; - } - a->a_postorder = (basicblock **)PyObject_Malloc( - sizeof(basicblock *) * nblocks); - if (!a->a_postorder) { - PyErr_NoMemory(); - return 0; - } - return 1; + memset(a, 0, sizeof(struct assembler)); + a->a_lineno = firstlineno; + a->a_bytecode = PyBytes_FromStringAndSize(NULL, DEFAULT_CODE_SIZE); + if (!a->a_bytecode) + return 0; + a->a_lnotab = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); + if (!a->a_lnotab) + return 0; + if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) { + PyErr_NoMemory(); + return 0; + } + a->a_postorder = (basicblock **)PyObject_Malloc( + sizeof(basicblock *) * nblocks); + if (!a->a_postorder) { + PyErr_NoMemory(); + return 0; + } + return 1; } static void assemble_free(struct assembler *a) { - Py_XDECREF(a->a_bytecode); - Py_XDECREF(a->a_lnotab); - if (a->a_postorder) - PyObject_Free(a->a_postorder); + Py_XDECREF(a->a_bytecode); + Py_XDECREF(a->a_lnotab); + if (a->a_postorder) + PyObject_Free(a->a_postorder); } /* Return the size of a basic block in bytes. */ @@ -3634,22 +3634,22 @@ assemble_free(struct assembler *a) static int instrsize(struct instr *instr) { - if (!instr->i_hasarg) - return 1; /* 1 byte for the opcode*/ - if (instr->i_oparg > 0xffff) - return 6; /* 1 (opcode) + 1 (EXTENDED_ARG opcode) + 2 (oparg) + 2(oparg extended) */ - return 3; /* 1 (opcode) + 2 (oparg) */ + if (!instr->i_hasarg) + return 1; /* 1 byte for the opcode*/ + if (instr->i_oparg > 0xffff) + return 6; /* 1 (opcode) + 1 (EXTENDED_ARG opcode) + 2 (oparg) + 2(oparg extended) */ + return 3; /* 1 (opcode) + 2 (oparg) */ } static int blocksize(basicblock *b) { - int i; - int size = 0; + int i; + int size = 0; - for (i = 0; i < b->b_iused; i++) - size += instrsize(&b->b_instr[i]); - return size; + for (i = 0; i < b->b_iused; i++) + size += instrsize(&b->b_instr[i]); + return size; } /* Appends a pair to the end of the line number table, a_lnotab, representing @@ -3659,94 +3659,94 @@ blocksize(basicblock *b) static int assemble_lnotab(struct assembler *a, struct instr *i) { - int d_bytecode, d_lineno; - int len; - unsigned char *lnotab; - - d_bytecode = a->a_offset - a->a_lineno_off; - 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; - - if (d_bytecode > 255) { - int j, nbytes, ncodes = d_bytecode / 255; - nbytes = a->a_lnotab_off + 2 * ncodes; - len = PyBytes_GET_SIZE(a->a_lnotab); - if (nbytes >= len) { - if ((len <= INT_MAX / 2) && (len * 2 < nbytes)) - len = nbytes; - else if (len <= INT_MAX / 2) - len *= 2; - else { - PyErr_NoMemory(); - return 0; - } - if (_PyBytes_Resize(&a->a_lnotab, len) < 0) - return 0; - } - lnotab = (unsigned char *) - PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - for (j = 0; j < ncodes; j++) { - *lnotab++ = 255; - *lnotab++ = 0; - } - 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; - nbytes = a->a_lnotab_off + 2 * ncodes; - len = PyBytes_GET_SIZE(a->a_lnotab); - if (nbytes >= len) { - if ((len <= INT_MAX / 2) && len * 2 < nbytes) - len = nbytes; - else if (len <= INT_MAX / 2) - len *= 2; - else { - PyErr_NoMemory(); - return 0; - } - if (_PyBytes_Resize(&a->a_lnotab, len) < 0) - return 0; - } - lnotab = (unsigned char *) - PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - *lnotab++ = d_bytecode; - *lnotab++ = 255; - d_bytecode = 0; - for (j = 1; j < ncodes; j++) { - *lnotab++ = 0; - *lnotab++ = 255; - } - d_lineno -= ncodes * 255; - a->a_lnotab_off += ncodes * 2; - } - - len = PyBytes_GET_SIZE(a->a_lnotab); - if (a->a_lnotab_off + 2 >= len) { - if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0) - return 0; - } - lnotab = (unsigned char *) - PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - - a->a_lnotab_off += 2; - if (d_bytecode) { - *lnotab++ = d_bytecode; - *lnotab++ = d_lineno; - } - else { /* First line of a block; def stmt, etc. */ - *lnotab++ = 0; - *lnotab++ = d_lineno; - } - a->a_lineno = i->i_lineno; - a->a_lineno_off = a->a_offset; - return 1; + int d_bytecode, d_lineno; + int len; + unsigned char *lnotab; + + d_bytecode = a->a_offset - a->a_lineno_off; + 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; + + if (d_bytecode > 255) { + int j, nbytes, ncodes = d_bytecode / 255; + nbytes = a->a_lnotab_off + 2 * ncodes; + len = PyBytes_GET_SIZE(a->a_lnotab); + if (nbytes >= len) { + if ((len <= INT_MAX / 2) && (len * 2 < nbytes)) + len = nbytes; + else if (len <= INT_MAX / 2) + len *= 2; + else { + PyErr_NoMemory(); + return 0; + } + if (_PyBytes_Resize(&a->a_lnotab, len) < 0) + return 0; + } + lnotab = (unsigned char *) + PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + for (j = 0; j < ncodes; j++) { + *lnotab++ = 255; + *lnotab++ = 0; + } + 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; + nbytes = a->a_lnotab_off + 2 * ncodes; + len = PyBytes_GET_SIZE(a->a_lnotab); + if (nbytes >= len) { + if ((len <= INT_MAX / 2) && len * 2 < nbytes) + len = nbytes; + else if (len <= INT_MAX / 2) + len *= 2; + else { + PyErr_NoMemory(); + return 0; + } + if (_PyBytes_Resize(&a->a_lnotab, len) < 0) + return 0; + } + lnotab = (unsigned char *) + PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + *lnotab++ = d_bytecode; + *lnotab++ = 255; + d_bytecode = 0; + for (j = 1; j < ncodes; j++) { + *lnotab++ = 0; + *lnotab++ = 255; + } + d_lineno -= ncodes * 255; + a->a_lnotab_off += ncodes * 2; + } + + len = PyBytes_GET_SIZE(a->a_lnotab); + if (a->a_lnotab_off + 2 >= len) { + if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0) + return 0; + } + lnotab = (unsigned char *) + PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + + a->a_lnotab_off += 2; + if (d_bytecode) { + *lnotab++ = d_bytecode; + *lnotab++ = d_lineno; + } + else { /* First line of a block; def stmt, etc. */ + *lnotab++ = 0; + *lnotab++ = d_lineno; + } + a->a_lineno = i->i_lineno; + a->a_lineno_off = a->a_offset; + return 1; } /* assemble_emit() @@ -3757,227 +3757,227 @@ assemble_lnotab(struct assembler *a, struct instr *i) static int assemble_emit(struct assembler *a, struct instr *i) { - int size, arg = 0, ext = 0; - Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode); - char *code; - - size = instrsize(i); - if (i->i_hasarg) { - arg = i->i_oparg; - ext = arg >> 16; - } - if (i->i_lineno && !assemble_lnotab(a, i)) - return 0; - if (a->a_offset + size >= len) { - if (len > PY_SSIZE_T_MAX / 2) - return 0; - if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) - return 0; - } - code = PyBytes_AS_STRING(a->a_bytecode) + a->a_offset; - a->a_offset += size; - if (size == 6) { - assert(i->i_hasarg); - *code++ = (char)EXTENDED_ARG; - *code++ = ext & 0xff; - *code++ = ext >> 8; - arg &= 0xffff; - } - *code++ = i->i_opcode; - if (i->i_hasarg) { - assert(size == 3 || size == 6); - *code++ = arg & 0xff; - *code++ = arg >> 8; - } - return 1; + int size, arg = 0, ext = 0; + Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode); + char *code; + + size = instrsize(i); + if (i->i_hasarg) { + arg = i->i_oparg; + ext = arg >> 16; + } + if (i->i_lineno && !assemble_lnotab(a, i)) + return 0; + if (a->a_offset + size >= len) { + if (len > PY_SSIZE_T_MAX / 2) + return 0; + if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) + return 0; + } + code = PyBytes_AS_STRING(a->a_bytecode) + a->a_offset; + a->a_offset += size; + if (size == 6) { + assert(i->i_hasarg); + *code++ = (char)EXTENDED_ARG; + *code++ = ext & 0xff; + *code++ = ext >> 8; + arg &= 0xffff; + } + *code++ = i->i_opcode; + if (i->i_hasarg) { + assert(size == 3 || size == 6); + *code++ = arg & 0xff; + *code++ = arg >> 8; + } + return 1; } static void assemble_jump_offsets(struct assembler *a, struct compiler *c) { - basicblock *b; - int bsize, totsize, extended_arg_count = 0, last_extended_arg_count; - int i; - - /* Compute the size of each block and fixup jump args. - Replace block pointer with position in bytecode. */ - do { - totsize = 0; - for (i = a->a_nblocks - 1; i >= 0; i--) { - b = a->a_postorder[i]; - bsize = blocksize(b); - b->b_offset = totsize; - totsize += bsize; - } - last_extended_arg_count = extended_arg_count; - extended_arg_count = 0; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - bsize = b->b_offset; - for (i = 0; i < b->b_iused; i++) { - struct instr *instr = &b->b_instr[i]; - /* Relative jumps are computed relative to - the instruction pointer after fetching - the jump instruction. - */ - bsize += instrsize(instr); - if (instr->i_jabs) - instr->i_oparg = instr->i_target->b_offset; - else if (instr->i_jrel) { - int delta = instr->i_target->b_offset - bsize; - instr->i_oparg = delta; - } - else - continue; - if (instr->i_oparg > 0xffff) - extended_arg_count++; - } - } - - /* XXX: This is an awful hack that could hurt performance, but - on the bright side it should work until we come up - with a better solution. - - The issue is that in the first loop blocksize() is called - which calls instrsize() which requires i_oparg be set - appropriately. There is a bootstrap problem because - i_oparg is calculated in the second loop above. - - So we loop until we stop seeing new EXTENDED_ARGs. - The only EXTENDED_ARGs that could be popping up are - ones in jump instructions. So this should converge - fairly quickly. - */ - } while (last_extended_arg_count != extended_arg_count); + basicblock *b; + int bsize, totsize, extended_arg_count = 0, last_extended_arg_count; + int i; + + /* Compute the size of each block and fixup jump args. + Replace block pointer with position in bytecode. */ + do { + totsize = 0; + for (i = a->a_nblocks - 1; i >= 0; i--) { + b = a->a_postorder[i]; + bsize = blocksize(b); + b->b_offset = totsize; + totsize += bsize; + } + last_extended_arg_count = extended_arg_count; + extended_arg_count = 0; + for (b = c->u->u_blocks; b != NULL; b = b->b_list) { + bsize = b->b_offset; + for (i = 0; i < b->b_iused; i++) { + struct instr *instr = &b->b_instr[i]; + /* Relative jumps are computed relative to + the instruction pointer after fetching + the jump instruction. + */ + bsize += instrsize(instr); + if (instr->i_jabs) + instr->i_oparg = instr->i_target->b_offset; + else if (instr->i_jrel) { + int delta = instr->i_target->b_offset - bsize; + instr->i_oparg = delta; + } + else + continue; + if (instr->i_oparg > 0xffff) + extended_arg_count++; + } + } + + /* XXX: This is an awful hack that could hurt performance, but + on the bright side it should work until we come up + with a better solution. + + The issue is that in the first loop blocksize() is called + which calls instrsize() which requires i_oparg be set + appropriately. There is a bootstrap problem because + i_oparg is calculated in the second loop above. + + So we loop until we stop seeing new EXTENDED_ARGs. + The only EXTENDED_ARGs that could be popping up are + ones in jump instructions. So this should converge + fairly quickly. + */ + } while (last_extended_arg_count != extended_arg_count); } static PyObject * dict_keys_inorder(PyObject *dict, int offset) { - PyObject *tuple, *k, *v; - Py_ssize_t i, pos = 0, size = PyDict_Size(dict); - - tuple = PyTuple_New(size); - if (tuple == NULL) - return NULL; - while (PyDict_Next(dict, &pos, &k, &v)) { - i = PyLong_AS_LONG(v); - /* The keys of the dictionary are tuples. (see compiler_add_o) - The object we want is always first, though. */ - k = PyTuple_GET_ITEM(k, 0); - Py_INCREF(k); - assert((i - offset) < size); - assert((i - offset) >= 0); - PyTuple_SET_ITEM(tuple, i - offset, k); - } - return tuple; + PyObject *tuple, *k, *v; + Py_ssize_t i, pos = 0, size = PyDict_Size(dict); + + tuple = PyTuple_New(size); + if (tuple == NULL) + return NULL; + while (PyDict_Next(dict, &pos, &k, &v)) { + i = PyLong_AS_LONG(v); + /* The keys of the dictionary are tuples. (see compiler_add_o) + The object we want is always first, though. */ + k = PyTuple_GET_ITEM(k, 0); + Py_INCREF(k); + assert((i - offset) < size); + assert((i - offset) >= 0); + PyTuple_SET_ITEM(tuple, i - offset, k); + } + return tuple; } static int 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) { - if (!ste->ste_unoptimized) - flags |= CO_OPTIMIZED; - if (ste->ste_nested) - flags |= CO_NESTED; - if (ste->ste_generator) - flags |= CO_GENERATOR; - if (ste->ste_varargs) - flags |= CO_VARARGS; - if (ste->ste_varkeywords) - flags |= CO_VARKEYWORDS; - } - - /* (Only) inherit compilerflags in PyCF_MASK */ - flags |= (c->c_flags->cf_flags & PyCF_MASK); - - n = PyDict_Size(c->u->u_freevars); - if (n < 0) - return -1; - if (n == 0) { - n = PyDict_Size(c->u->u_cellvars); - if (n < 0) - return -1; - if (n == 0) { - flags |= CO_NOFREE; - } - } - - return flags; + PySTEntryObject *ste = c->u->u_ste; + int flags = 0, n; + if (ste->ste_type != ModuleBlock) + flags |= CO_NEWLOCALS; + if (ste->ste_type == FunctionBlock) { + if (!ste->ste_unoptimized) + flags |= CO_OPTIMIZED; + if (ste->ste_nested) + flags |= CO_NESTED; + if (ste->ste_generator) + flags |= CO_GENERATOR; + if (ste->ste_varargs) + flags |= CO_VARARGS; + if (ste->ste_varkeywords) + flags |= CO_VARKEYWORDS; + } + + /* (Only) inherit compilerflags in PyCF_MASK */ + flags |= (c->c_flags->cf_flags & PyCF_MASK); + + n = PyDict_Size(c->u->u_freevars); + if (n < 0) + return -1; + if (n == 0) { + n = PyDict_Size(c->u->u_cellvars); + if (n < 0) + return -1; + if (n == 0) { + flags |= CO_NOFREE; + } + } + + return flags; } static PyCodeObject * makecode(struct compiler *c, struct assembler *a) { - PyObject *tmp; - PyCodeObject *co = NULL; - PyObject *consts = NULL; - PyObject *names = NULL; - PyObject *varnames = NULL; - PyObject *filename = NULL; - PyObject *name = NULL; - PyObject *freevars = NULL; - PyObject *cellvars = NULL; - PyObject *bytecode = NULL; - int nlocals, flags; - - tmp = dict_keys_inorder(c->u->u_consts, 0); - if (!tmp) - goto error; - consts = PySequence_List(tmp); /* optimize_code requires a list */ - Py_DECREF(tmp); - - names = dict_keys_inorder(c->u->u_names, 0); - varnames = dict_keys_inorder(c->u->u_varnames, 0); - if (!consts || !names || !varnames) - goto error; - - cellvars = dict_keys_inorder(c->u->u_cellvars, 0); - if (!cellvars) - goto error; - freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); - if (!freevars) - goto error; - filename = PyUnicode_DecodeFSDefault(c->c_filename); - if (!filename) - goto error; - - nlocals = PyDict_Size(c->u->u_varnames); - flags = compute_code_flags(c); - if (flags < 0) - goto error; - - bytecode = PyCode_Optimize(a->a_bytecode, consts, names, a->a_lnotab); - if (!bytecode) - goto error; - - tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */ - if (!tmp) - goto error; - Py_DECREF(consts); - consts = tmp; - - co = PyCode_New(c->u->u_argcount, c->u->u_kwonlyargcount, - nlocals, stackdepth(c), flags, - bytecode, consts, names, varnames, - freevars, cellvars, - filename, c->u->u_name, - c->u->u_firstlineno, - a->a_lnotab); + PyObject *tmp; + PyCodeObject *co = NULL; + PyObject *consts = NULL; + PyObject *names = NULL; + PyObject *varnames = NULL; + PyObject *filename = NULL; + PyObject *name = NULL; + PyObject *freevars = NULL; + PyObject *cellvars = NULL; + PyObject *bytecode = NULL; + int nlocals, flags; + + tmp = dict_keys_inorder(c->u->u_consts, 0); + if (!tmp) + goto error; + consts = PySequence_List(tmp); /* optimize_code requires a list */ + Py_DECREF(tmp); + + names = dict_keys_inorder(c->u->u_names, 0); + varnames = dict_keys_inorder(c->u->u_varnames, 0); + if (!consts || !names || !varnames) + goto error; + + cellvars = dict_keys_inorder(c->u->u_cellvars, 0); + if (!cellvars) + goto error; + freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); + if (!freevars) + goto error; + filename = PyUnicode_DecodeFSDefault(c->c_filename); + if (!filename) + goto error; + + nlocals = PyDict_Size(c->u->u_varnames); + flags = compute_code_flags(c); + if (flags < 0) + goto error; + + bytecode = PyCode_Optimize(a->a_bytecode, consts, names, a->a_lnotab); + if (!bytecode) + goto error; + + tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */ + if (!tmp) + goto error; + Py_DECREF(consts); + consts = tmp; + + co = PyCode_New(c->u->u_argcount, c->u->u_kwonlyargcount, + nlocals, stackdepth(c), flags, + bytecode, consts, names, varnames, + freevars, cellvars, + filename, c->u->u_name, + c->u->u_firstlineno, + a->a_lnotab); error: - Py_XDECREF(consts); - Py_XDECREF(names); - Py_XDECREF(varnames); - Py_XDECREF(filename); - Py_XDECREF(name); - Py_XDECREF(freevars); - Py_XDECREF(cellvars); - Py_XDECREF(bytecode); - return co; + Py_XDECREF(consts); + Py_XDECREF(names); + Py_XDECREF(varnames); + Py_XDECREF(filename); + Py_XDECREF(name); + Py_XDECREF(freevars); + Py_XDECREF(cellvars); + Py_XDECREF(bytecode); + return co; } @@ -3986,90 +3986,90 @@ makecode(struct compiler *c, struct assembler *a) static void dump_instr(const struct instr *i) { - const char *jrel = i->i_jrel ? "jrel " : ""; - const char *jabs = i->i_jabs ? "jabs " : ""; - char arg[128]; + const char *jrel = i->i_jrel ? "jrel " : ""; + const char *jabs = i->i_jabs ? "jabs " : ""; + char arg[128]; - *arg = '\0'; - if (i->i_hasarg) - sprintf(arg, "arg: %d ", i->i_oparg); + *arg = '\0'; + if (i->i_hasarg) + sprintf(arg, "arg: %d ", i->i_oparg); - fprintf(stderr, "line: %d, opcode: %d %s%s%s\n", - i->i_lineno, i->i_opcode, arg, jabs, jrel); + fprintf(stderr, "line: %d, opcode: %d %s%s%s\n", + i->i_lineno, i->i_opcode, arg, jabs, jrel); } static void dump_basicblock(const basicblock *b) { - const char *seen = b->b_seen ? "seen " : ""; - const char *b_return = b->b_return ? "return " : ""; - fprintf(stderr, "used: %d, depth: %d, offset: %d %s%s\n", - b->b_iused, b->b_startdepth, b->b_offset, seen, b_return); - if (b->b_instr) { - int i; - for (i = 0; i < b->b_iused; i++) { - fprintf(stderr, " [%02d] ", i); - dump_instr(b->b_instr + i); - } - } + const char *seen = b->b_seen ? "seen " : ""; + const char *b_return = b->b_return ? "return " : ""; + fprintf(stderr, "used: %d, depth: %d, offset: %d %s%s\n", + b->b_iused, b->b_startdepth, b->b_offset, seen, b_return); + if (b->b_instr) { + int i; + for (i = 0; i < b->b_iused; i++) { + fprintf(stderr, " [%02d] ", i); + dump_instr(b->b_instr + i); + } + } } #endif static PyCodeObject * assemble(struct compiler *c, int addNone) { - basicblock *b, *entryblock; - struct assembler a; - int i, j, nblocks; - PyCodeObject *co = NULL; - - /* Make sure every block that falls off the end returns None. - XXX NEXT_BLOCK() isn't quite right, because if the last - block ends with a jump or return b_next shouldn't set. - */ - if (!c->u->u_curblock->b_return) { - NEXT_BLOCK(c); - if (addNone) - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, RETURN_VALUE); - } - - nblocks = 0; - entryblock = NULL; - for (b = c->u->u_blocks; b != NULL; b = b->b_list) { - nblocks++; - entryblock = b; - } - - /* Set firstlineno if it wasn't explicitly set. */ - if (!c->u->u_firstlineno) { - if (entryblock && entryblock->b_instr) - c->u->u_firstlineno = entryblock->b_instr->i_lineno; - else - c->u->u_firstlineno = 1; - } - if (!assemble_init(&a, nblocks, c->u->u_firstlineno)) - goto error; - dfs(c, entryblock, &a); - - /* Can't modify the bytecode after computing jump offsets. */ - assemble_jump_offsets(&a, c); - - /* Emit code in reverse postorder from dfs. */ - for (i = a.a_nblocks - 1; i >= 0; i--) { - b = a.a_postorder[i]; - for (j = 0; j < b->b_iused; j++) - if (!assemble_emit(&a, &b->b_instr[j])) - goto error; - } - - if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) - goto error; - if (_PyBytes_Resize(&a.a_bytecode, a.a_offset) < 0) - goto error; - - co = makecode(c, &a); + basicblock *b, *entryblock; + struct assembler a; + int i, j, nblocks; + PyCodeObject *co = NULL; + + /* Make sure every block that falls off the end returns None. + XXX NEXT_BLOCK() isn't quite right, because if the last + block ends with a jump or return b_next shouldn't set. + */ + if (!c->u->u_curblock->b_return) { + NEXT_BLOCK(c); + if (addNone) + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, RETURN_VALUE); + } + + nblocks = 0; + entryblock = NULL; + for (b = c->u->u_blocks; b != NULL; b = b->b_list) { + nblocks++; + entryblock = b; + } + + /* Set firstlineno if it wasn't explicitly set. */ + if (!c->u->u_firstlineno) { + if (entryblock && entryblock->b_instr) + c->u->u_firstlineno = entryblock->b_instr->i_lineno; + else + c->u->u_firstlineno = 1; + } + if (!assemble_init(&a, nblocks, c->u->u_firstlineno)) + goto error; + dfs(c, entryblock, &a); + + /* Can't modify the bytecode after computing jump offsets. */ + assemble_jump_offsets(&a, c); + + /* Emit code in reverse postorder from dfs. */ + for (i = a.a_nblocks - 1; i >= 0; i--) { + b = a.a_postorder[i]; + for (j = 0; j < b->b_iused; j++) + if (!assemble_emit(&a, &b->b_instr[j])) + goto error; + } + + if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) + goto error; + if (_PyBytes_Resize(&a.a_bytecode, a.a_offset) < 0) + goto error; + + co = makecode(c, &a); error: - assemble_free(&a); - return co; + assemble_free(&a); + return co; } -- cgit v1.2.1 From 86ae93c37f42628dac90832d2194e39afa157539 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 17 Jun 2010 23:08:50 +0000 Subject: Issue #6543: Write the traceback in the terminal encoding instead of utf-8. Fix the encoding of the modules filename. Reindent also traceback.h, just because I hate tabs :-) --- 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 fa7dcef5fb..c9f6e8d701 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3942,7 +3942,7 @@ makecode(struct compiler *c, struct assembler *a) freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_DecodeFSDefault(c->c_filename); + filename = PyUnicode_FromString(c->c_filename); if (!filename) goto error; -- cgit v1.2.1 From 9d5759dfe84bb0a234a76e5b0a9e8440f3a56f24 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Tue, 22 Jun 2010 21:49:39 +0000 Subject: Merged revisions 82169 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r82169 | antoine.pitrou | 2010-06-22 23:42:05 +0200 (mar., 22 juin 2010) | 4 lines Fix misindents in compile.c (for Benjamin). Of course, whoever used the wrong indentation rules needs to be spanked. ........ --- Python/compile.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index c9f6e8d701..aae0339c2c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -968,7 +968,7 @@ compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, { int arg = compiler_add_o(c, dict, o); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -979,11 +979,11 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, int arg; PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) - return 0; + return 0; arg = compiler_add_o(c, dict, mangled); Py_DECREF(mangled); if (arg < 0) - return 0; + return 0; return compiler_addop_i(c, opcode, arg); } @@ -1134,7 +1134,7 @@ static int compiler_isdocstring(stmt_ty s) { if (s->kind != Expr_kind) - return 0; + return 0; return s->v.Expr.value->kind == Str_kind; } @@ -1240,11 +1240,11 @@ compiler_lookup_arg(PyObject *dict, PyObject *name) PyObject *k, *v; k = PyTuple_Pack(2, name, name->ob_type); if (k == NULL) - return -1; + return -1; v = PyDict_GetItem(dict, k); Py_DECREF(k); if (v == NULL) - return -1; + return -1; return PyLong_AS_LONG(v); } @@ -3073,7 +3073,7 @@ compiler_with(struct compiler *c, stmt_ty s) block = compiler_new_block(c); finally = compiler_new_block(c); if (!block || !finally) - return 0; + return 0; /* Evaluate EXPR */ VISIT(c, expr, s->v.With.context_expr); @@ -3082,15 +3082,15 @@ compiler_with(struct compiler *c, stmt_ty s) /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); if (!compiler_push_fblock(c, FINALLY_TRY, block)) { - return 0; + return 0; } if (s->v.With.optional_vars) { - VISIT(c, expr, s->v.With.optional_vars); + VISIT(c, expr, s->v.With.optional_vars); } else { /* Discard result from context.__enter__() */ - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); } /* BLOCK code */ @@ -3103,7 +3103,7 @@ compiler_with(struct compiler *c, stmt_ty s) ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); if (!compiler_push_fblock(c, FINALLY_END, finally)) - return 0; + return 0; /* Finally block starts; context.__exit__ is on the stack under the exception or return information. Just issue our magic -- cgit v1.2.1 From a1047ef59eacea8f3b31386bb6c4a766d6237fd7 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Jul 2010 22:37:19 +0000 Subject: move test_trace.py so as not to conflict with future tests for the trace module --- 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 aae0339c2c..83c9e0211e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -787,6 +787,7 @@ opcode_stack_effect(int opcode, int oparg) case LOAD_CONST: return 1; case LOAD_NAME: + case LOAD_NAME_LOCAL_ONLY: return 1; case BUILD_TUPLE: case BUILD_LIST: @@ -2481,6 +2482,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) optype = OP_DEREF; break; case LOCAL: + case LOCAL_ONLY: if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; @@ -2556,7 +2558,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) break; case OP_NAME: switch (ctx) { - case Load: op = LOAD_NAME; break; + case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: -- cgit v1.2.1 From b1dabe110111af235ea2829b44e9e9f44aed91ef Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Jul 2010 22:39:34 +0000 Subject: revert unintended changes --- Python/compile.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 83c9e0211e..aae0339c2c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -787,7 +787,6 @@ opcode_stack_effect(int opcode, int oparg) case LOAD_CONST: return 1; case LOAD_NAME: - case LOAD_NAME_LOCAL_ONLY: return 1; case BUILD_TUPLE: case BUILD_LIST: @@ -2482,7 +2481,6 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) optype = OP_DEREF; break; case LOCAL: - case LOCAL_ONLY: if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_FAST; break; @@ -2558,7 +2556,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) break; case OP_NAME: switch (ctx) { - case Load: op = (scope == LOCAL_ONLY) ? LOAD_NAME_LOCAL_ONLY : LOAD_NAME; break; + case Load: op = LOAD_NAME; break; case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: -- cgit v1.2.1 From 6b5b7721253d41df7f38576e7874e79e1f8c0ee3 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sat, 4 Sep 2010 18:43:52 +0000 Subject: Issue #9225: Remove the ROT_FOUR and DUP_TOPX opcode, the latter replaced by the new (and simpler) DUP_TOP_TWO. Performance isn't changed, but our bytecode is a bit simplified. Patch by Demur Rumed. --- Python/compile.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index aae0339c2c..6963a151a7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -680,8 +680,8 @@ opcode_stack_effect(int opcode, int oparg) return 0; case DUP_TOP: return 1; - case ROT_FOUR: - return 0; + case DUP_TOP_TWO: + return 2; case UNARY_POSITIVE: case UNARY_NEGATIVE: @@ -782,8 +782,6 @@ opcode_stack_effect(int opcode, int oparg) return -1; case DELETE_GLOBAL: return 0; - case DUP_TOPX: - return oparg; case LOAD_CONST: return 1; case LOAD_NAME: @@ -3404,7 +3402,7 @@ compiler_handle_subscr(struct compiler *c, const char *kind, return 0; } if (ctx == AugLoad) { - ADDOP_I(c, DUP_TOPX, 2); + ADDOP(c, DUP_TOP_TWO); } else if (ctx == AugStore) { ADDOP(c, ROT_THREE); -- cgit v1.2.1 From f4136c2c8d5c2470640d04074c10b9e576c0e4fb Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 10 Sep 2010 21:39:53 +0000 Subject: #4617: Previously it was illegal to delete a name from the local namespace if it occurs as a free variable in a nested block. This limitation of the compiler has been lifted, and a new opcode introduced (DELETE_DEREF). This sample was valid in 2.6, but fails to compile in 3.x without this change:: >>> def f(): ... def print_error(): ... print(e) ... try: ... something ... except Exception as e: ... print_error() ... # implicit "del e" here This sample has always been invalid in Python, and now works:: >>> def outer(x): ... def inner(): ... return x ... inner() ... del x There is no need to bump the PYC magic number: the new opcode is used for code that did not compile before. --- Python/compile.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 6963a151a7..5341e6b535 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -857,6 +857,8 @@ opcode_stack_effect(int opcode, int oparg) return 1; case STORE_DEREF: return -1; + case DELETE_DEREF: + return 0; default: fprintf(stderr, "opcode = %d\n", opcode); Py_FatalError("opcode_stack_effect()"); @@ -2506,13 +2508,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) case AugLoad: case AugStore: break; - case Del: - PyErr_Format(PyExc_SyntaxError, - "can not delete variable '%S' referenced " - "in nested scope", - name); - Py_DECREF(mangled); - return 0; + case Del: op = DELETE_DEREF; break; case Param: default: PyErr_SetString(PyExc_SystemError, -- cgit v1.2.1 From c9651975ec1a9b373c4da03a83f5e5abe12b23b9 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 20 Sep 2010 23:02:10 +0000 Subject: add column offset to all syntax errors --- Python/compile.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 5341e6b535..d29e48c47a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -123,6 +123,7 @@ struct compiler_unit { int u_firstlineno; /* the first lineno of the block */ int u_lineno; /* the lineno for the current stmt */ + int u_col_offset; /* the offset of the current stmt */ int u_lineno_set; /* boolean to indicate whether instr has been generated with current lineno */ }; @@ -486,6 +487,7 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; + u->u_col_offset = 0; u->u_lineno_set = 0; u->u_consts = PyDict_New(); if (!u->u_consts) { @@ -1965,6 +1967,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) return compiler_error(c, "default 'except:' must be last"); c->u->u_lineno_set = 0; c->u->u_lineno = handler->lineno; + c->u->u_col_offset = handler->col_offset; except = compiler_new_block(c); if (except == NULL) return 0; @@ -2247,6 +2250,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) /* Always assign a lineno to the next instruction for a stmt. */ c->u->u_lineno = s->lineno; + c->u->u_col_offset = s->col_offset; c->u->u_lineno_set = 0; switch (s->kind) { @@ -3122,6 +3126,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e) c->u->u_lineno = e->lineno; c->u->u_lineno_set = 0; } + /* Updating the column offset is always harmless. */ + c->u->u_col_offset = e->col_offset; switch (e->kind) { case BoolOp_kind: return compiler_boolop(c, e); @@ -3363,8 +3369,8 @@ compiler_error(struct compiler *c, const char *errstr) Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, - Py_None, loc); + u = Py_BuildValue("(ziiO)", c->c_filename, c->u->u_lineno, + c->u->u_col_offset, loc); if (!u) goto exit; v = Py_BuildValue("(zO)", errstr, u); -- cgit v1.2.1 From 24c7fa3b4d2daf8a3b9d1b3c143e6a55b5b2b4d5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 16 Oct 2010 13:14:10 +0000 Subject: Issue #9713, #10114: Parser functions (eg. PyParser_ASTFromFile) expects filenames encoded to the filesystem encoding with surrogateescape error handler (to support undecodable bytes), instead of UTF-8 in strict mode. --- 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 d29e48c47a..1ff085909c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3942,7 +3942,7 @@ makecode(struct compiler *c, struct assembler *a) freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_FromString(c->c_filename); + filename = PyUnicode_DecodeFSDefault(c->c_filename); if (!filename) goto error; -- cgit v1.2.1 From f6b0658c48183a6162922a03e4b843a5d2af1bb7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 17 Oct 2010 19:16:33 +0000 Subject: compiler_error(): use PyUnicode_DecodeFSDefault() to decode the filename, instead of utf-8 in strict mode. --- Python/compile.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 1ff085909c..fb2759650b 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3361,7 +3361,7 @@ compiler_in_loop(struct compiler *c) { static int compiler_error(struct compiler *c, const char *errstr) { - PyObject *loc; + PyObject *loc, *filename; PyObject *u = NULL, *v = NULL; loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); @@ -3369,7 +3369,16 @@ compiler_error(struct compiler *c, const char *errstr) Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(ziiO)", c->c_filename, c->u->u_lineno, + if (c->c_filename != NULL) { + filename = PyUnicode_DecodeFSDefault(c->c_filename); + if (!filename) + goto exit; + } + else { + Py_INCREF(Py_None); + filename = Py_None; + } + u = Py_BuildValue("(NiiO)", filename, c->u->u_lineno, c->u->u_col_offset, loc); if (!u) goto exit; -- cgit v1.2.1 From c16ad2eeb23a20667e832e09ad88e012952d8988 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Tue, 30 Nov 2010 09:41:01 +0000 Subject: Remove redundant includes of headers that are already included by Python.h. --- 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 fb2759650b..dfb2c9bcf7 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -25,10 +25,8 @@ #include "Python-ast.h" #include "node.h" -#include "pyarena.h" #include "ast.h" #include "code.h" -#include "compile.h" #include "symtable.h" #include "opcode.h" -- cgit v1.2.1 From e652f1b1b4166521e134d6312eebe9b761ea78e5 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 4 Dec 2010 10:26:46 +0000 Subject: Add an "optimize" parameter to compile() to control the optimization level, and provide an interface to it in py_compile, compileall and PyZipFile. --- Python/compile.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index dfb2c9bcf7..1d6e38c22e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -139,6 +139,7 @@ struct compiler { PyFutureFeatures *c_future; /* pointer to module's __future__ */ PyCompilerFlags *c_flags; + int c_optimize; /* optimization level */ int c_interactive; /* true if in interactive mode */ int c_nestlevel; @@ -175,7 +176,7 @@ static void compiler_pop_fblock(struct compiler *, enum fblocktype, static int compiler_in_loop(struct compiler *); static int inplace_binop(struct compiler *, operator_ty); -static int expr_constant(expr_ty e); +static int expr_constant(struct compiler *, expr_ty); static int compiler_with(struct compiler *, stmt_ty); static int compiler_call_helper(struct compiler *c, int n, @@ -254,8 +255,8 @@ compiler_init(struct compiler *c) } PyCodeObject * -PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, - PyArena *arena) +PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, + int optimize, PyArena *arena) { struct compiler c; PyCodeObject *co = NULL; @@ -283,6 +284,7 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, c.c_future->ff_features = merged; flags->cf_flags = merged; c.c_flags = flags; + c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; c.c_st = PySymtable_Build(mod, filename, c.c_future); @@ -1149,7 +1151,7 @@ compiler_body(struct compiler *c, asdl_seq *stmts) if (!asdl_seq_LEN(stmts)) return 1; st = (stmt_ty)asdl_seq_GET(stmts, 0); - if (compiler_isdocstring(st) && Py_OptimizeFlag < 2) { + if (compiler_isdocstring(st) && c->c_optimize < 2) { /* don't generate docstrings if -OO */ i = 1; VISIT(c, expr, st->v.Expr.value); @@ -1463,7 +1465,7 @@ compiler_function(struct compiler *c, stmt_ty s) st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0); docstring = compiler_isdocstring(st); - if (docstring && Py_OptimizeFlag < 2) + if (docstring && c->c_optimize < 2) 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); @@ -1697,7 +1699,7 @@ compiler_if(struct compiler *c, stmt_ty s) if (end == NULL) return 0; - constant = expr_constant(s->v.If.test); + constant = expr_constant(c, s->v.If.test); /* constant = 0: "if 0" * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ @@ -1759,7 +1761,7 @@ static int compiler_while(struct compiler *c, stmt_ty s) { basicblock *loop, *orelse, *end, *anchor = NULL; - int constant = expr_constant(s->v.While.test); + int constant = expr_constant(c, s->v.While.test); if (constant == 0) { if (s->v.While.orelse) @@ -2211,7 +2213,7 @@ compiler_assert(struct compiler *c, stmt_ty s) static PyObject *assertion_error = NULL; basicblock *end; - if (Py_OptimizeFlag) + if (c->c_optimize) return 1; if (assertion_error == NULL) { assertion_error = PyUnicode_InternFromString("AssertionError"); @@ -3011,7 +3013,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) */ static int -expr_constant(expr_ty e) +expr_constant(struct compiler *c, expr_ty e) { char *id; switch (e->kind) { @@ -3029,7 +3031,7 @@ expr_constant(expr_ty e) if (strcmp(id, "False") == 0) return 0; if (strcmp(id, "None") == 0) return 0; if (strcmp(id, "__debug__") == 0) - return ! Py_OptimizeFlag; + return ! c->c_optimize; /* fall through */ default: return -1; @@ -4080,3 +4082,13 @@ assemble(struct compiler *c, int addNone) assemble_free(&a); return co; } + +#undef PyAST_Compile +PyAPI_FUNC(PyCodeObject *) +PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, + PyArena *arena) +{ + return PyAST_CompileEx(mod, filename, flags, -1, arena); +} + + -- cgit v1.2.1