diff options
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 4452 |
1 files changed, 1168 insertions, 3284 deletions
diff --git a/Python/compile.c b/Python/compile.c index 98a4afa..6386a40 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -24,12 +24,15 @@ #include "Python.h" #include "Python-ast.h" -#include "pycore_pystate.h" /* _PyInterpreterState_GET_UNSAFE() */ +#include "node.h" +#include "pyarena.h" #include "ast.h" #include "code.h" +#include "compile.h" #include "symtable.h" #include "opcode.h" -#include "wordcode_helpers.h" + +int Py_OptimizeFlag = 0; #define DEFAULT_BLOCK_SIZE 16 #define DEFAULT_BLOCKS 8 @@ -37,13 +40,13 @@ #define DEFAULT_LNOTAB_SIZE 16 #define COMP_GENEXP 0 -#define COMP_LISTCOMP 1 -#define COMP_SETCOMP 2 -#define COMP_DICTCOMP 3 +#define COMP_SETCOMP 1 +#define COMP_DICTCOMP 2 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) */ @@ -81,25 +84,11 @@ It's called a frame block to distinguish it from a basic block in the compiler IR. */ -enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END, - WITH, ASYNC_WITH, HANDLER_CLEANUP, POP_VALUE }; +enum fblocktype { LOOP, EXCEPT, FINALLY_TRY, FINALLY_END }; struct fblockinfo { enum fblocktype fb_type; basicblock *fb_block; - /* (optional) type-specific exit or cleanup block */ - basicblock *fb_exit; - /* (optional) additional information required for unwinding */ - void *fb_datum; -}; - -enum { - COMPILER_SCOPE_MODULE, - COMPILER_SCOPE_CLASS, - COMPILER_SCOPE_FUNCTION, - COMPILER_SCOPE_ASYNC_FUNCTION, - COMPILER_SCOPE_LAMBDA, - COMPILER_SCOPE_COMPREHENSION, }; /* The following items change on entry and exit of code blocks. @@ -109,9 +98,6 @@ struct compiler_unit { PySTEntryObject *u_ste; PyObject *u_name; - PyObject *u_qualname; /* dot-separated qualified name (lazy) */ - int u_scope_type; - /* 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. @@ -124,9 +110,7 @@ struct compiler_unit { PyObject *u_private; /* for private name mangling */ - Py_ssize_t u_argcount; /* number of arguments for block */ - Py_ssize_t u_posonlyargcount; /* number of positional only arguments for block */ - Py_ssize_t u_kwonlyargcount; /* number of keyword only arguments for block */ + int u_argcount; /* number of 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; @@ -137,8 +121,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 + bool u_lineno_set; /* boolean to indicate whether instr has been generated with current lineno */ }; @@ -147,44 +130,32 @@ struct compiler_unit { 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 managed by compiler_enter_scope() and compiler_exit_scope(). - -Note that we don't track recursion levels during compilation - the -task of detecting and rejecting excessive levels of nesting is -handled by the symbol analysis pass. - */ struct compiler { - PyObject *c_filename; + const char *c_filename; struct symtable *c_st; 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; - int c_do_not_emit_bytecode; /* The compiler won't emit any bytecode - if this value is different from zero. - This can be used to temporarily visit - nodes without emitting bytecode to - check only errors. */ - - PyObject *c_const_cache; /* Python dict holding all constants, - including names tuple */ + 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, int, void *, int); +static int compiler_enter_scope(struct compiler *, identifier, void *, int); static void compiler_free(struct compiler *); static basicblock *compiler_new_block(struct compiler *); static int compiler_next_instr(struct compiler *, basicblock *); static int compiler_addop(struct compiler *, int); -static int compiler_addop_i(struct compiler *, int, Py_ssize_t); +static int compiler_addop_o(struct compiler *, int, PyObject *, PyObject *); +static int compiler_addop_i(struct compiler *, int, int); static int compiler_addop_j(struct compiler *, int, basicblock *, int); +static basicblock *compiler_use_new_block(struct compiler *); static int compiler_error(struct compiler *, const char *); -static int compiler_warn(struct compiler *, const char *, ...); static int compiler_nameop(struct compiler *, identifier, expr_context_ty); static PyCodeObject *compiler_mod(struct compiler *, mod_ty); @@ -192,54 +163,41 @@ static int compiler_visit_stmt(struct compiler *, stmt_ty); 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_annassign(struct compiler *, stmt_ty); static int compiler_visit_slice(struct compiler *, slice_ty, expr_context_ty); +static int compiler_push_fblock(struct compiler *, enum fblocktype, + basicblock *); +static void compiler_pop_fblock(struct compiler *, enum fblocktype, + basicblock *); +/* Returns true if there is a loop on the fblock stack. */ +static int compiler_in_loop(struct compiler *); + static int inplace_binop(struct compiler *, operator_ty); -static int are_all_items_const(asdl_seq *, Py_ssize_t, Py_ssize_t); -static int expr_constant(expr_ty); - -static int compiler_with(struct compiler *, stmt_ty, int); -static int compiler_async_with(struct compiler *, stmt_ty, int); -static int compiler_async_for(struct compiler *, stmt_ty); -static int compiler_call_helper(struct compiler *c, int n, - asdl_seq *args, - asdl_seq *keywords); -static int compiler_try_except(struct compiler *, stmt_ty); -static int compiler_set_qualname(struct compiler *); - -static int compiler_sync_comprehension_generator( - struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type); - -static int compiler_async_comprehension_generator( - struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type); +static int expr_constant(expr_ty e); + +static int compiler_with(struct compiler *, stmt_ty); static PyCodeObject *assemble(struct compiler *, int addNone); -static PyObject *__doc__, *__annotations__; +static PyObject *__doc__; -#define CAPSULE_NAME "compile.c compiler unit" +#define COMPILER_CAPSULE_NAME_COMPILER_UNIT "compile.c compiler unit" PyObject * _Py_Mangle(PyObject *privateobj, PyObject *ident) { /* Name mangling: __private becomes _classname__private. This is independent from how the name is used. */ - PyObject *result; - size_t nlen, plen, ipriv; - Py_UCS4 maxchar; - if (privateobj == NULL || !PyUnicode_Check(privateobj) || - PyUnicode_READ_CHAR(ident, 0) != '_' || - PyUnicode_READ_CHAR(ident, 1) != '_') { + const char *p, *name = PyString_AsString(ident); + char *buffer; + size_t nlen, plen; + if (privateobj == NULL || !PyString_Check(privateobj) || + name == NULL || name[0] != '_' || name[1] != '_') { Py_INCREF(ident); return ident; } - nlen = PyUnicode_GET_LENGTH(ident); - plen = PyUnicode_GET_LENGTH(privateobj); + p = PyString_AsString(privateobj); + nlen = strlen(name); /* Don't mangle __id__ or names with dots. The only time a name with a dot can occur is when @@ -249,47 +207,35 @@ _Py_Mangle(PyObject *privateobj, PyObject *ident) TODO(jhylton): Decide whether we want to support mangling of the module name, e.g. __M.X. */ - if ((PyUnicode_READ_CHAR(ident, nlen-1) == '_' && - PyUnicode_READ_CHAR(ident, nlen-2) == '_') || - PyUnicode_FindChar(ident, '.', 0, nlen, 1) != -1) { + if ((name[nlen-1] == '_' && name[nlen-2] == '_') + || strchr(name, '.')) { Py_INCREF(ident); return ident; /* Don't mangle __whatever__ */ } /* Strip leading underscores from class name */ - ipriv = 0; - while (PyUnicode_READ_CHAR(privateobj, ipriv) == '_') - ipriv++; - if (ipriv == plen) { + while (*p == '_') + p++; + if (*p == '\0') { Py_INCREF(ident); return ident; /* Don't mangle if class is just underscores */ } - plen -= ipriv; + plen = strlen(p); - if (plen + nlen >= PY_SSIZE_T_MAX - 1) { + if (nlen >= PY_SSIZE_T_MAX - 1 - plen) { PyErr_SetString(PyExc_OverflowError, "private identifier too large to be mangled"); return NULL; } - maxchar = PyUnicode_MAX_CHAR_VALUE(ident); - if (PyUnicode_MAX_CHAR_VALUE(privateobj) > maxchar) - maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj); - - result = PyUnicode_New(1 + nlen + plen, maxchar); - if (!result) + ident = PyString_FromStringAndSize(NULL, 1 + nlen + plen); + if (!ident) return 0; - /* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */ - PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_'); - if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) { - Py_DECREF(result); - return NULL; - } - if (PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen) < 0) { - Py_DECREF(result); - return NULL; - } - assert(_PyUnicode_CheckConsistency(result, 1)); - return result; + /* ident = "_" + p[:plen] + name # i.e. 1+plen+nlen bytes */ + buffer = PyString_AS_STRING(ident); + buffer[0] = '_'; + memcpy(buffer+1, p, plen); + strcpy(buffer+1+plen, name); + return ident; } static int @@ -297,64 +243,46 @@ compiler_init(struct compiler *c) { memset(c, 0, sizeof(struct compiler)); - c->c_const_cache = PyDict_New(); - if (!c->c_const_cache) { - return 0; - } - c->c_stack = PyList_New(0); - if (!c->c_stack) { - Py_CLEAR(c->c_const_cache); + if (!c->c_stack) return 0; - } return 1; } PyCodeObject * -PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, - int optimize, PyArena *arena) +PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, + PyArena *arena) { struct compiler c; PyCodeObject *co = NULL; - PyCompilerFlags local_flags = _PyCompilerFlags_INIT; + PyCompilerFlags local_flags; int merged; - PyConfig *config = &_PyInterpreterState_GET_UNSAFE()->config; if (!__doc__) { - __doc__ = PyUnicode_InternFromString("__doc__"); + __doc__ = PyString_InternFromString("__doc__"); if (!__doc__) return NULL; } - if (!__annotations__) { - __annotations__ = PyUnicode_InternFromString("__annotations__"); - if (!__annotations__) - return NULL; - } + if (!compiler_init(&c)) return NULL; - Py_INCREF(filename); c.c_filename = filename; c.c_arena = arena; - c.c_future = PyFuture_FromASTObject(mod, filename); + 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_optimize = (optimize == -1) ? config->optimization_level : optimize; c.c_nestlevel = 0; - c.c_do_not_emit_bytecode = 0; - if (!_PyAST_Optimize(mod, arena, c.c_optimize)) { - goto finally; - } - - c.c_st = PySymtable_BuildObject(mod, filename, c.c_future); + c.c_st = PySymtable_Build(mod, filename, c.c_future); if (c.c_st == NULL) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_SystemError, "no symtable"); @@ -370,21 +298,6 @@ PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, } PyCodeObject * -PyAST_CompileEx(mod_ty mod, const char *filename_str, PyCompilerFlags *flags, - int optimize, PyArena *arena) -{ - PyObject *filename; - PyCodeObject *co; - filename = PyUnicode_DecodeFSDefault(filename_str); - if (filename == NULL) - return NULL; - co = PyAST_CompileObject(mod, filename, flags, optimize, arena); - Py_DECREF(filename); - return co; - -} - -PyCodeObject * PyNode_Compile(struct _node *n, const char *filename) { PyCodeObject *co = NULL; @@ -406,8 +319,6 @@ compiler_free(struct compiler *c) PySymtable_Free(c->c_st); if (c->c_future) PyObject_Free(c->c_future); - Py_XDECREF(c->c_filename); - Py_DECREF(c->c_const_cache); Py_DECREF(c->c_stack); } @@ -421,17 +332,20 @@ list2dict(PyObject *list) n = PyList_Size(list); for (i = 0; i < n; i++) { - v = PyLong_FromSsize_t(i); + v = PyInt_FromLong(i); if (!v) { Py_DECREF(dict); return NULL; } k = PyList_GET_ITEM(list, i); - if (PyDict_SetItem(dict, k, v) < 0) { + k = _PyCode_ConstantKey(k); + 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; @@ -446,7 +360,7 @@ each key. */ static PyObject * -dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) +dictbytype(PyObject *src, int scope_type, int flag, int offset) { Py_ssize_t i = offset, scope, num_keys, key_i; PyObject *k, *v, *dest = PyDict_New(); @@ -471,29 +385,30 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) num_keys = PyList_GET_SIZE(sorted_keys); for (key_i = 0; key_i < num_keys; key_i++) { - /* XXX this should probably be a macro in symtable.h */ - long vi; k = PyList_GET_ITEM(sorted_keys, key_i); v = PyDict_GetItem(src, k); - assert(PyLong_Check(v)); - vi = PyLong_AS_LONG(v); - scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK; + /* XXX this should probably be a macro in symtable.h */ + assert(PyInt_Check(v)); + scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK; - if (scope == scope_type || vi & flag) { - PyObject *item = PyLong_FromSsize_t(i); + if (scope == scope_type || PyInt_AS_LONG(v) & flag) { + PyObject *tuple, *item = PyInt_FromLong(i); if (item == NULL) { Py_DECREF(sorted_keys); Py_DECREF(dest); return NULL; } i++; - if (PyDict_SetItem(dest, k, item) < 0) { + tuple = _PyCode_ConstantKey(k); + if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) { Py_DECREF(sorted_keys); Py_DECREF(item); Py_DECREF(dest); + Py_XDECREF(tuple); return NULL; } Py_DECREF(item); + Py_DECREF(tuple); } } Py_DECREF(sorted_keys); @@ -505,9 +420,9 @@ compiler_unit_check(struct compiler_unit *u) { basicblock *block; for (block = u->u_blocks; block != NULL; block = block->b_list) { - assert((uintptr_t)block != 0xcbcbcbcbU); - assert((uintptr_t)block != 0xfbfbfbfbU); - assert((uintptr_t)block != 0xdbdbdbdbU); + 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); @@ -536,7 +451,6 @@ compiler_unit_free(struct compiler_unit *u) } Py_CLEAR(u->u_ste); Py_CLEAR(u->u_name); - Py_CLEAR(u->u_qualname); Py_CLEAR(u->u_consts); Py_CLEAR(u->u_names); Py_CLEAR(u->u_varnames); @@ -547,11 +461,10 @@ compiler_unit_free(struct compiler_unit *u) } static int -compiler_enter_scope(struct compiler *c, identifier name, - int scope_type, void *key, int lineno) +compiler_enter_scope(struct compiler *c, identifier name, void *key, + int lineno) { struct compiler_unit *u; - basicblock *block; u = (struct compiler_unit *)PyObject_Malloc(sizeof( struct compiler_unit)); @@ -560,10 +473,7 @@ compiler_enter_scope(struct compiler *c, identifier name, return 0; } memset(u, 0, sizeof(struct compiler_unit)); - u->u_scope_type = scope_type; u->u_argcount = 0; - u->u_posonlyargcount = 0; - u->u_kwonlyargcount = 0; u->u_ste = PySymtable_Lookup(c->c_st, key); if (!u->u_ste) { compiler_unit_free(u); @@ -577,27 +487,9 @@ compiler_enter_scope(struct compiler *c, identifier name, compiler_unit_free(u); return 0; } - if (u->u_ste->ste_needs_class_closure) { - /* Cook up an implicit __class__ cell. */ - _Py_IDENTIFIER(__class__); - PyObject *name; - int res; - assert(u->u_scope_type == COMPILER_SCOPE_CLASS); - assert(PyDict_GET_SIZE(u->u_cellvars) == 0); - name = _PyUnicode_FromId(&PyId___class__); - if (!name) { - compiler_unit_free(u); - return 0; - } - res = PyDict_SetItem(u->u_cellvars, name, _PyLong_Zero); - if (res < 0) { - compiler_unit_free(u); - return 0; - } - } u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, - PyDict_GET_SIZE(u->u_cellvars)); + PyDict_Size(u->u_cellvars)); if (!u->u_freevars) { compiler_unit_free(u); return 0; @@ -607,8 +499,7 @@ compiler_enter_scope(struct compiler *c, identifier name, u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; - u->u_col_offset = 0; - u->u_lineno_set = 0; + u->u_lineno_set = false; u->u_consts = PyDict_New(); if (!u->u_consts) { compiler_unit_free(u); @@ -624,7 +515,7 @@ compiler_enter_scope(struct compiler *c, identifier name, /* Push the old compiler_unit on the stack. */ if (c->u) { - PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL); + 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); @@ -637,16 +528,8 @@ compiler_enter_scope(struct compiler *c, identifier name, c->u = u; c->c_nestlevel++; - - block = compiler_new_block(c); - if (block == NULL) + if (compiler_use_new_block(c) == NULL) return 0; - c->u->u_curblock = block; - - if (u->u_scope_type != COMPILER_SCOPE_MODULE) { - if (!compiler_set_qualname(c)) - return 0; - } return 1; } @@ -654,7 +537,7 @@ compiler_enter_scope(struct compiler *c, identifier name, static void compiler_exit_scope(struct compiler *c) { - Py_ssize_t n; + int n; PyObject *capsule; c->c_nestlevel--; @@ -663,7 +546,7 @@ compiler_exit_scope(struct compiler *c) 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, CAPSULE_NAME); + 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) @@ -675,83 +558,6 @@ compiler_exit_scope(struct compiler *c) } -static int -compiler_set_qualname(struct compiler *c) -{ - _Py_static_string(dot, "."); - _Py_static_string(dot_locals, ".<locals>"); - Py_ssize_t stack_size; - struct compiler_unit *u = c->u; - PyObject *name, *base, *dot_str, *dot_locals_str; - - base = NULL; - stack_size = PyList_GET_SIZE(c->c_stack); - assert(stack_size >= 1); - if (stack_size > 1) { - int scope, force_global = 0; - struct compiler_unit *parent; - PyObject *mangled, *capsule; - - capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); - parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); - assert(parent); - - if (u->u_scope_type == COMPILER_SCOPE_FUNCTION - || u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION - || u->u_scope_type == COMPILER_SCOPE_CLASS) { - assert(u->u_name); - mangled = _Py_Mangle(parent->u_private, u->u_name); - if (!mangled) - return 0; - scope = PyST_GetScope(parent->u_ste, mangled); - Py_DECREF(mangled); - assert(scope != GLOBAL_IMPLICIT); - if (scope == GLOBAL_EXPLICIT) - force_global = 1; - } - - if (!force_global) { - if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION - || parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION - || parent->u_scope_type == COMPILER_SCOPE_LAMBDA) { - dot_locals_str = _PyUnicode_FromId(&dot_locals); - if (dot_locals_str == NULL) - return 0; - base = PyUnicode_Concat(parent->u_qualname, dot_locals_str); - if (base == NULL) - return 0; - } - else { - Py_INCREF(parent->u_qualname); - base = parent->u_qualname; - } - } - } - - if (base != NULL) { - dot_str = _PyUnicode_FromId(&dot); - if (dot_str == NULL) { - Py_DECREF(base); - return 0; - } - name = PyUnicode_Concat(base, dot_str); - Py_DECREF(base); - if (name == NULL) - return 0; - PyUnicode_Append(&name, u->u_name); - if (name == NULL) - return 0; - } - else { - Py_INCREF(u->u_name); - name = u->u_name; - } - u->u_qualname = name; - - return 1; -} - - /* Allocate a new block and return a pointer to it. Returns NULL on error. */ @@ -776,6 +582,16 @@ compiler_new_block(struct compiler *c) } static basicblock * +compiler_use_new_block(struct compiler *c) +{ + basicblock *block = compiler_new_block(c); + if (block == NULL) + return NULL; + c->u->u_curblock = block; + return block; +} + +static basicblock * compiler_next_block(struct compiler *c) { basicblock *block = compiler_new_block(c); @@ -821,7 +637,7 @@ compiler_next_instr(struct compiler *c, basicblock *b) oldsize = b->b_ialloc * sizeof(struct instr); newsize = oldsize << 1; - if (oldsize > (SIZE_MAX >> 1)) { + if (oldsize > (PY_SIZE_MAX >> 1)) { PyErr_NoMemory(); return -1; } @@ -851,7 +667,7 @@ compiler_next_instr(struct compiler *c, basicblock *b) - when entering a new scope - on each statement - on each expression that start a new line - - before the "except" and "finally" clauses + - before the "except" clause - before the "for" and "while" expressions */ @@ -861,59 +677,42 @@ compiler_set_lineno(struct compiler *c, int off) basicblock *b; if (c->u->u_lineno_set) return; - c->u->u_lineno_set = 1; + c->u->u_lineno_set = true; b = c->u->u_curblock; b->b_instr[off].i_lineno = c->u->u_lineno; } -/* Return the stack effect of opcode with argument oparg. - - Some opcodes have different stack effect when jump to the target and - when not jump. The 'jump' parameter specifies the case: - - * 0 -- when not jump - * 1 -- when jump - * -1 -- maximal - */ -/* XXX Make the stack effect of WITH_CLEANUP_START and - WITH_CLEANUP_FINISH deterministic. */ static int -stack_effect(int opcode, int oparg, int jump) +opcode_stack_effect(int opcode, int oparg) { switch (opcode) { - case NOP: - case EXTENDED_ARG: - return 0; - - /* Stack manipulation */ case POP_TOP: return -1; case ROT_TWO: case ROT_THREE: - case ROT_FOUR: return 0; case DUP_TOP: return 1; - case DUP_TOP_TWO: - return 2; + case ROT_FOUR: + return 0; - /* Unary operators */ case UNARY_POSITIVE: case UNARY_NEGATIVE: case UNARY_NOT: + case UNARY_CONVERT: case UNARY_INVERT: return 0; case SET_ADD: case LIST_APPEND: return -1; + case MAP_ADD: return -2; - /* Binary operators */ case BINARY_POWER: case BINARY_MULTIPLY: - case BINARY_MATRIX_MULTIPLY: + case BINARY_DIVIDE: case BINARY_MODULO: case BINARY_ADD: case BINARY_SUBTRACT: @@ -925,14 +724,43 @@ stack_effect(int opcode, int oparg, int jump) case INPLACE_TRUE_DIVIDE: return -1; + case SLICE+0: + return 0; + case SLICE+1: + return -1; + case SLICE+2: + return -1; + case SLICE+3: + return -2; + + case STORE_SLICE+0: + return -2; + case STORE_SLICE+1: + return -3; + case STORE_SLICE+2: + return -3; + case STORE_SLICE+3: + return -4; + + case DELETE_SLICE+0: + return -1; + case DELETE_SLICE+1: + return -2; + case DELETE_SLICE+2: + return -2; + case DELETE_SLICE+3: + return -3; + case INPLACE_ADD: case INPLACE_SUBTRACT: case INPLACE_MULTIPLY: - case INPLACE_MATRIX_MULTIPLY: + case INPLACE_DIVIDE: case INPLACE_MODULO: return -1; case STORE_SUBSCR: return -3; + case STORE_MAP: + return -2; case DELETE_SUBSCR: return -2; @@ -949,34 +777,44 @@ stack_effect(int opcode, int oparg, int jump) case PRINT_EXPR: return -1; - case LOAD_BUILD_CLASS: - return 1; + case PRINT_ITEM: + return -1; + case PRINT_NEWLINE: + return 0; + case PRINT_ITEM_TO: + return -2; + case PRINT_NEWLINE_TO: + 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: - /* 1 in the normal flow. - * Restore the stack position and push 6 values before jumping to - * the handler if an exception be raised. */ - return jump ? 6 : 1; + return 4; + case WITH_CLEANUP: + return -1; /* XXX Sometimes more */ + case LOAD_LOCALS: + return 1; case RETURN_VALUE: return -1; case IMPORT_STAR: return -1; - case SETUP_ANNOTATIONS: - return 0; + case EXEC_STMT: + return -3; case YIELD_VALUE: return 0; - case YIELD_FROM: - return -1; + case POP_BLOCK: return 0; - case POP_EXCEPT: - return -3; + case END_FINALLY: + return -3; /* or -1 or -2 if no exception occurred or + return/break/continue */ + case BUILD_CLASS: + return -2; case STORE_NAME: return -1; @@ -984,11 +822,8 @@ stack_effect(int opcode, int oparg, int jump) return 0; case UNPACK_SEQUENCE: return oparg-1; - case UNPACK_EX: - return (oparg&0xFF) + (oparg>>8); case FOR_ITER: - /* -1 at end of iterator, 1 if continue iterating. */ - return jump > 0 ? -1 : 1; + return 1; /* or -1, at end of iterator */ case STORE_ATTR: return -2; @@ -998,6 +833,8 @@ stack_effect(int opcode, int oparg, int jump) return -1; case DELETE_GLOBAL: return 0; + case DUP_TOPX: + return oparg; case LOAD_CONST: return 1; case LOAD_NAME: @@ -1005,19 +842,9 @@ stack_effect(int opcode, int oparg, int jump) case BUILD_TUPLE: case BUILD_LIST: case BUILD_SET: - case BUILD_STRING: return 1-oparg; - case BUILD_LIST_UNPACK: - case BUILD_TUPLE_UNPACK: - case BUILD_TUPLE_UNPACK_WITH_CALL: - case BUILD_SET_UNPACK: - case BUILD_MAP_UNPACK: - case BUILD_MAP_UNPACK_WITH_CALL: - return 1 - oparg; case BUILD_MAP: - return 1 - 2*oparg; - case BUILD_CONST_KEY_MAP: - return -oparg; + return 1; case LOAD_ATTR: return 0; case COMPARE_OP: @@ -1027,15 +854,12 @@ stack_effect(int opcode, int oparg, int jump) case IMPORT_FROM: return 1; - /* Jumps */ 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 JUMP_IF_TRUE_OR_POP: - case JUMP_IF_FALSE_OR_POP: - return jump ? 0 : -1; - case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: return -1; @@ -1043,17 +867,12 @@ stack_effect(int opcode, int oparg, int jump) case LOAD_GLOBAL: return 1; - /* Exception handling */ + case CONTINUE_LOOP: + return 0; + case SETUP_LOOP: + case SETUP_EXCEPT: case SETUP_FINALLY: - /* 0 in the normal flow. - * Restore the stack position and push 6 values before jumping to - * the handler if an exception be raised. */ - return jump ? 6 : 0; - case RERAISE: - return -3; - - case WITH_EXCEPT_START: - return 1; + return 0; case LOAD_FAST: return 1; @@ -1064,79 +883,37 @@ stack_effect(int opcode, int oparg, int jump) case RAISE_VARARGS: return -oparg; - - /* Functions and calls */ +#define NARGS(o) (((o) % 256) + 2*((o) / 256)) case CALL_FUNCTION: - return -oparg; - case CALL_METHOD: - return -oparg-1; + return -NARGS(oparg); + case CALL_FUNCTION_VAR: case CALL_FUNCTION_KW: - return -oparg-1; - case CALL_FUNCTION_EX: - return -1 - ((oparg & 0x01) != 0); + return -NARGS(oparg)-1; + case CALL_FUNCTION_VAR_KW: + return -NARGS(oparg)-2; +#undef NARGS case MAKE_FUNCTION: - return -1 - ((oparg & 0x01) != 0) - ((oparg & 0x02) != 0) - - ((oparg & 0x04) != 0) - ((oparg & 0x08) != 0); + return -oparg; case BUILD_SLICE: if (oparg == 3) return -2; else return -1; - /* Closures */ + case MAKE_CLOSURE: + return -oparg-1; case LOAD_CLOSURE: return 1; case LOAD_DEREF: - case LOAD_CLASSDEREF: return 1; case STORE_DEREF: return -1; - case DELETE_DEREF: - return 0; - - /* Iterators and generators */ - case GET_AWAITABLE: - return 0; - case SETUP_ASYNC_WITH: - /* 0 in the normal flow. - * Restore the stack position to the position before the result - * of __aenter__ and push 6 values before jumping to the handler - * if an exception be raised. */ - return jump ? -1 + 6 : 0; - case BEFORE_ASYNC_WITH: - return 1; - case GET_AITER: - return 0; - case GET_ANEXT: - return 1; - case GET_YIELD_FROM_ITER: - return 0; - case END_ASYNC_FOR: - return -7; - case FORMAT_VALUE: - /* If there's a fmt_spec on the stack, we go from 2->1, - else 1->1. */ - return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0; - case LOAD_METHOD: - return 1; - case LOAD_ASSERTION_ERROR: - return 1; default: - return PY_INVALID_STACK_EFFECT; - } - return PY_INVALID_STACK_EFFECT; /* not reachable */ -} - -int -PyCompile_OpcodeStackEffectWithJump(int opcode, int oparg, int jump) -{ - return stack_effect(opcode, oparg, jump); -} + fprintf(stderr, "opcode = %d\n", opcode); + Py_FatalError("opcode_stack_effect()"); -int -PyCompile_OpcodeStackEffect(int opcode, int oparg) -{ - return stack_effect(opcode, oparg, -1); + } + return 0; /* not reachable */ } /* Add an opcode with no argument. @@ -1149,199 +926,55 @@ compiler_addop(struct compiler *c, int opcode) basicblock *b; struct instr *i; int off; - assert(!HAS_ARG(opcode)); - if (c->c_do_not_emit_bytecode) { - return 1; - } 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_oparg = 0; + i->i_hasarg = 0; if (opcode == RETURN_VALUE) b->b_return = 1; compiler_set_lineno(c, off); return 1; } -static Py_ssize_t +static int compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) { - PyObject *v; + PyObject *t, *v; Py_ssize_t arg; - v = PyDict_GetItemWithError(dict, o); + t = _PyCode_ConstantKey(o); + if (t == NULL) + return -1; + + v = PyDict_GetItem(dict, t); if (!v) { - if (PyErr_Occurred()) { - return -1; - } - arg = PyDict_GET_SIZE(dict); - v = PyLong_FromSsize_t(arg); + arg = PyDict_Size(dict); + v = PyInt_FromLong(arg); if (!v) { + Py_DECREF(t); return -1; } - if (PyDict_SetItem(dict, o, v) < 0) { + if (PyDict_SetItem(dict, t, v) < 0) { + Py_DECREF(t); Py_DECREF(v); return -1; } Py_DECREF(v); } else - arg = PyLong_AsLong(v); - return arg; -} - -// Merge const *o* recursively and return constant key object. -static PyObject* -merge_consts_recursive(struct compiler *c, PyObject *o) -{ - // None and Ellipsis are singleton, and key is the singleton. - // No need to merge object and key. - if (o == Py_None || o == Py_Ellipsis) { - Py_INCREF(o); - return o; - } - - PyObject *key = _PyCode_ConstantKey(o); - if (key == NULL) { - return NULL; - } - - // t is borrowed reference - PyObject *t = PyDict_SetDefault(c->c_const_cache, key, key); - if (t != key) { - // o is registered in c_const_cache. Just use it. - Py_XINCREF(t); - Py_DECREF(key); - return t; - } - - // We registered o in c_const_cache. - // When o is a tuple or frozenset, we want to merge its - // items too. - if (PyTuple_CheckExact(o)) { - Py_ssize_t len = PyTuple_GET_SIZE(o); - for (Py_ssize_t i = 0; i < len; i++) { - PyObject *item = PyTuple_GET_ITEM(o, i); - PyObject *u = merge_consts_recursive(c, item); - if (u == NULL) { - Py_DECREF(key); - return NULL; - } - - // See _PyCode_ConstantKey() - PyObject *v; // borrowed - if (PyTuple_CheckExact(u)) { - v = PyTuple_GET_ITEM(u, 1); - } - else { - v = u; - } - if (v != item) { - Py_INCREF(v); - PyTuple_SET_ITEM(o, i, v); - Py_DECREF(item); - } - - Py_DECREF(u); - } - } - else if (PyFrozenSet_CheckExact(o)) { - // *key* is tuple. And its first item is frozenset of - // constant keys. - // See _PyCode_ConstantKey() for detail. - assert(PyTuple_CheckExact(key)); - assert(PyTuple_GET_SIZE(key) == 2); - - Py_ssize_t len = PySet_GET_SIZE(o); - if (len == 0) { // empty frozenset should not be re-created. - return key; - } - PyObject *tuple = PyTuple_New(len); - if (tuple == NULL) { - Py_DECREF(key); - return NULL; - } - Py_ssize_t i = 0, pos = 0; - PyObject *item; - Py_hash_t hash; - while (_PySet_NextEntry(o, &pos, &item, &hash)) { - PyObject *k = merge_consts_recursive(c, item); - if (k == NULL) { - Py_DECREF(tuple); - Py_DECREF(key); - return NULL; - } - PyObject *u; - if (PyTuple_CheckExact(k)) { - u = PyTuple_GET_ITEM(k, 1); - Py_INCREF(u); - Py_DECREF(k); - } - else { - u = k; - } - PyTuple_SET_ITEM(tuple, i, u); // Steals reference of u. - i++; - } - - // Instead of rewriting o, we create new frozenset and embed in the - // key tuple. Caller should get merged frozenset from the key tuple. - PyObject *new = PyFrozenSet_New(tuple); - Py_DECREF(tuple); - if (new == NULL) { - Py_DECREF(key); - return NULL; - } - assert(PyTuple_GET_ITEM(key, 1) == o); - Py_DECREF(o); - PyTuple_SET_ITEM(key, 1, new); - } - - return key; -} - -static Py_ssize_t -compiler_add_const(struct compiler *c, PyObject *o) -{ - if (c->c_do_not_emit_bytecode) { - return 0; - } - - PyObject *key = merge_consts_recursive(c, o); - if (key == NULL) { - return -1; - } - - Py_ssize_t arg = compiler_add_o(c, c->u->u_consts, key); - Py_DECREF(key); + arg = PyInt_AsLong(v); + Py_DECREF(t); return arg; } static int -compiler_addop_load_const(struct compiler *c, PyObject *o) -{ - if (c->c_do_not_emit_bytecode) { - return 1; - } - - Py_ssize_t arg = compiler_add_const(c, o); - if (arg < 0) - return 0; - return compiler_addop_i(c, LOAD_CONST, arg); -} - -static int compiler_addop_o(struct compiler *c, int opcode, PyObject *dict, PyObject *o) { - if (c->c_do_not_emit_bytecode) { - return 1; - } - - Py_ssize_t arg = compiler_add_o(c, dict, o); + int arg = compiler_add_o(c, dict, o); if (arg < 0) return 0; return compiler_addop_i(c, opcode, arg); @@ -1351,12 +984,7 @@ static int compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, PyObject *o) { - Py_ssize_t arg; - - if (c->c_do_not_emit_bytecode) { - return 1; - } - + int arg; PyObject *mangled = _Py_Mangle(c->u->u_private, o); if (!mangled) return 0; @@ -1372,31 +1000,17 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, */ static int -compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg) +compiler_addop_i(struct compiler *c, int opcode, int oparg) { struct instr *i; int off; - - if (c->c_do_not_emit_bytecode) { - return 1; - } - - /* oparg value is unsigned, but a signed C int is usually used to store - it in the C code (like Python/ceval.c). - - Limit to 32-bit signed C int (rather than INT_MAX) for portability. - - The argument of a concrete bytecode instruction is limited to 8-bit. - EXTENDED_ARG is used for 16, 24, and 32-bit arguments. */ - assert(HAS_ARG(opcode)); - assert(0 <= oparg && oparg <= 2147483647); - 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 = Py_SAFE_DOWNCAST(oparg, Py_ssize_t, int); + i->i_oparg = oparg; + i->i_hasarg = 1; compiler_set_lineno(c, off); return 1; } @@ -1407,11 +1021,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) struct instr *i; int off; - if (c->c_do_not_emit_bytecode) { - return 1; - } - - assert(HAS_ARG(opcode)); assert(b != NULL); off = compiler_next_instr(c, c->u->u_curblock); if (off < 0) @@ -1419,6 +1028,7 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) 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 @@ -1427,12 +1037,22 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) return 1; } -/* NEXT_BLOCK() creates an implicit jump from the current block - to the new block. +/* 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. +*/ - The returns inside this macro make it impossible to decref objects - created in the local function. Local objects should use the arena. +/* The returns inside these macros make it impossible to decref objects + created in the local function. Local objects should use the arena. */ + + +#define NEW_BLOCK(C) { \ + if (compiler_use_new_block((C)) == NULL) \ + return 0; \ +} + #define NEXT_BLOCK(C) { \ if (compiler_next_block((C)) == NULL) \ return 0; \ @@ -1450,24 +1070,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) } \ } -#define ADDOP_LOAD_CONST(C, O) { \ - if (!compiler_addop_load_const((C), (O))) \ - return 0; \ -} - -/* Same as ADDOP_LOAD_CONST, but steals a reference. */ -#define ADDOP_LOAD_CONST_NEW(C, O) { \ - PyObject *__new_const = (O); \ - if (__new_const == NULL) { \ - return 0; \ - } \ - if (!compiler_addop_load_const((C), __new_const)) { \ - Py_DECREF(__new_const); \ - return 0; \ - } \ - Py_DECREF(__new_const); \ -} - #define ADDOP_O(C, OP, O, TYPE) { \ if (!compiler_addop_o((C), (OP), (C)->u->u_ ## TYPE, (O))) \ return 0; \ @@ -1545,268 +1147,31 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) } \ } -/* These macros allows to check only for errors and not emmit bytecode - * while visiting nodes. -*/ - -#define BEGIN_DO_NOT_EMIT_BYTECODE { \ - c->c_do_not_emit_bytecode++; - -#define END_DO_NOT_EMIT_BYTECODE \ - c->c_do_not_emit_bytecode--; \ -} - -/* Search if variable annotations are present statically in a block. */ - -static int -find_ann(asdl_seq *stmts) -{ - int i, j, res = 0; - stmt_ty st; - - for (i = 0; i < asdl_seq_LEN(stmts); i++) { - st = (stmt_ty)asdl_seq_GET(stmts, i); - switch (st->kind) { - case AnnAssign_kind: - return 1; - case For_kind: - res = find_ann(st->v.For.body) || - find_ann(st->v.For.orelse); - break; - case AsyncFor_kind: - res = find_ann(st->v.AsyncFor.body) || - find_ann(st->v.AsyncFor.orelse); - break; - case While_kind: - res = find_ann(st->v.While.body) || - find_ann(st->v.While.orelse); - break; - case If_kind: - res = find_ann(st->v.If.body) || - find_ann(st->v.If.orelse); - break; - case With_kind: - res = find_ann(st->v.With.body); - break; - case AsyncWith_kind: - res = find_ann(st->v.AsyncWith.body); - break; - case Try_kind: - for (j = 0; j < asdl_seq_LEN(st->v.Try.handlers); j++) { - excepthandler_ty handler = (excepthandler_ty)asdl_seq_GET( - st->v.Try.handlers, j); - if (find_ann(handler->v.ExceptHandler.body)) { - return 1; - } - } - res = find_ann(st->v.Try.body) || - find_ann(st->v.Try.finalbody) || - find_ann(st->v.Try.orelse); - break; - default: - res = 0; - } - if (res) { - break; - } - } - return res; -} - -/* - * Frame block handling functions - */ - -static int -compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b, - basicblock *exit, void *datum) -{ - struct fblockinfo *f; - if (c->u->u_nfblocks >= CO_MAXBLOCKS) { - PyErr_SetString(PyExc_SyntaxError, - "too many statically nested blocks"); - return 0; - } - f = &c->u->u_fblock[c->u->u_nfblocks++]; - f->fb_type = t; - f->fb_block = b; - f->fb_exit = exit; - f->fb_datum = datum; - 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); -} - static int -compiler_call_exit_with_nones(struct compiler *c) { - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, DUP_TOP); - ADDOP(c, DUP_TOP); - ADDOP_I(c, CALL_FUNCTION, 3); - return 1; -} - -/* Unwind a frame block. If preserve_tos is true, the TOS before - * popping the blocks will be restored afterwards, unless another - * return, break or continue is found. In which case, the TOS will - * be popped. - */ -static int -compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, - int preserve_tos) +compiler_isdocstring(stmt_ty s) { - switch (info->fb_type) { - case WHILE_LOOP: - return 1; - - case FOR_LOOP: - /* Pop the iterator */ - if (preserve_tos) { - ADDOP(c, ROT_TWO); - } - ADDOP(c, POP_TOP); - return 1; - - case EXCEPT: - ADDOP(c, POP_BLOCK); - return 1; - - case FINALLY_TRY: - ADDOP(c, POP_BLOCK); - if (preserve_tos) { - if (!compiler_push_fblock(c, POP_VALUE, NULL, NULL, NULL)) { - return 0; - } - } - VISIT_SEQ(c, stmt, info->fb_datum); - if (preserve_tos) { - compiler_pop_fblock(c, POP_VALUE, NULL); - } - return 1; - - case FINALLY_END: - if (preserve_tos) { - ADDOP(c, ROT_FOUR); - } - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - if (preserve_tos) { - ADDOP(c, ROT_FOUR); - } - ADDOP(c, POP_EXCEPT); - return 1; - - case WITH: - case ASYNC_WITH: - ADDOP(c, POP_BLOCK); - if (preserve_tos) { - ADDOP(c, ROT_TWO); - } - if(!compiler_call_exit_with_nones(c)) { - return 0; - } - if (info->fb_type == ASYNC_WITH) { - ADDOP(c, GET_AWAITABLE); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - } - ADDOP(c, POP_TOP); - return 1; - - case HANDLER_CLEANUP: - if (info->fb_datum) { - ADDOP(c, POP_BLOCK); - } - if (preserve_tos) { - ADDOP(c, ROT_FOUR); - } - ADDOP(c, POP_EXCEPT); - if (info->fb_datum) { - ADDOP_LOAD_CONST(c, Py_None); - compiler_nameop(c, info->fb_datum, Store); - compiler_nameop(c, info->fb_datum, Del); - } - return 1; - - case POP_VALUE: - if (preserve_tos) { - ADDOP(c, ROT_TWO); - } - ADDOP(c, POP_TOP); - return 1; - } - Py_UNREACHABLE(); -} - -/** Unwind block stack. If loop is not NULL, then stop when the first loop is encountered. */ -static int -compiler_unwind_fblock_stack(struct compiler *c, int preserve_tos, struct fblockinfo **loop) { - if (c->u->u_nfblocks == 0) { - return 1; - } - struct fblockinfo *top = &c->u->u_fblock[c->u->u_nfblocks-1]; - if (loop != NULL && (top->fb_type == WHILE_LOOP || top->fb_type == FOR_LOOP)) { - *loop = top; - return 1; - } - struct fblockinfo copy = *top; - c->u->u_nfblocks--; - if (!compiler_unwind_fblock(c, ©, preserve_tos)) { - return 0; - } - if (!compiler_unwind_fblock_stack(c, preserve_tos, loop)) { + if (s->kind != Expr_kind) return 0; - } - c->u->u_fblock[c->u->u_nfblocks] = copy; - c->u->u_nfblocks++; - return 1; + return s->v.Expr.value->kind == Str_kind; } -/* Compile a sequence of statements, checking for a docstring - and for annotations. */ +/* Compile a sequence of statements, checking for a docstring. */ static int compiler_body(struct compiler *c, asdl_seq *stmts) { int i = 0; stmt_ty st; - PyObject *docstring; - /* Set current line number to the line number of first statement. - This way line number for SETUP_ANNOTATIONS will always - coincide with the line number of first "real" statement in module. - If body is empty, then lineno will be set later in assemble. */ - if (c->u->u_scope_type == COMPILER_SCOPE_MODULE && - !c->u->u_lineno && asdl_seq_LEN(stmts)) { - st = (stmt_ty)asdl_seq_GET(stmts, 0); - c->u->u_lineno = st->lineno; - } - /* Every annotated class and module should have __annotations__. */ - if (find_ann(stmts)) { - ADDOP(c, SETUP_ANNOTATIONS); - } if (!asdl_seq_LEN(stmts)) return 1; - /* if not -OO mode, set docstring */ - if (c->c_optimize < 2) { - docstring = _PyAST_GetDocString(stmts); - if (docstring) { - i = 1; - st = (stmt_ty)asdl_seq_GET(stmts, 0); - assert(st->kind == Expr_kind); - VISIT(c, expr, st->v.Expr.value); - if (!compiler_nameop(c, __doc__, Store)) - return 0; - } + 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)); @@ -1820,12 +1185,12 @@ compiler_mod(struct compiler *c, mod_ty mod) int addNone = 1; static PyObject *module; if (!module) { - module = PyUnicode_InternFromString("<module>"); + module = PyString_InternFromString("<module>"); if (!module) return NULL; } /* Use 0 for firstlineno initially, will fixup in assemble(). */ - if (!compiler_enter_scope(c, module, COMPILER_SCOPE_MODULE, mod, 0)) + if (!compiler_enter_scope(c, module, mod, 0)) return NULL; switch (mod->kind) { case Module_kind: @@ -1835,9 +1200,6 @@ compiler_mod(struct compiler *c, mod_ty mod) } break; case Interactive_kind: - if (find_ann(mod->v.Interactive.body)) { - ADDOP(c, SETUP_ANNOTATIONS); - } c->c_interactive = 1; VISIT_SEQ_IN_SCOPE(c, stmt, mod->v.Interactive.body); @@ -1869,22 +1231,19 @@ compiler_mod(struct compiler *c, mod_ty mod) static int get_ref_type(struct compiler *c, PyObject *name) { - int scope; - if (c->u->u_scope_type == COMPILER_SCOPE_CLASS && - _PyUnicode_EqualToASCIIString(name, "__class__")) - return CELL; - scope = PyST_GetScope(c->u->u_ste, 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)\n" + "unknown scope for %.100s in %.100s(%s) in %s\n" "symbols: %s\nlocals: %s\nglobals: %s", - PyUnicode_AsUTF8(name), - PyUnicode_AsUTF8(c->u->u_name), - PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)), - PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)), - PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)), - PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)) + PyString_AS_STRING(name), + PyString_AS_STRING(c->u->u_name), + PyString_AS_STRING(PyObject_Repr(c->u->u_ste->ste_id)), + c->c_filename, + PyString_AS_STRING(PyObject_Repr(c->u->u_ste->ste_symbols)), + PyString_AS_STRING(PyObject_Repr(c->u->u_varnames)), + PyString_AS_STRING(PyObject_Repr(c->u->u_names)) ); Py_FatalError(buf); } @@ -1895,58 +1254,59 @@ get_ref_type(struct compiler *c, PyObject *name) static int compiler_lookup_arg(PyObject *dict, PyObject *name) { - PyObject *v; - v = PyDict_GetItem(dict, name); + PyObject *k, *v; + k = _PyCode_ConstantKey(name); + if (k == NULL) + return -1; + v = PyDict_GetItem(dict, k); + Py_DECREF(k); if (v == NULL) return -1; - return PyLong_AS_LONG(v); + return PyInt_AS_LONG(v); } static int -compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, PyObject *qualname) +compiler_make_closure(struct compiler *c, PyCodeObject *co, int args) { - Py_ssize_t i, free = PyCode_GetNumFree(co); - if (qualname == NULL) - qualname = co->co_name; - - if (free) { - 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 lookup 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", - PyUnicode_AsUTF8(PyObject_Repr(name)), - PyUnicode_AsUTF8(c->u->u_name), - reftype, arg, - PyUnicode_AsUTF8(co->co_name), - PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars))); - Py_FatalError("compiler_make_closure()"); - } - ADDOP_I(c, LOAD_CLOSURE, arg); - } - flags |= 0x08; - ADDOP_I(c, BUILD_TUPLE, free); + 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; } - ADDOP_LOAD_CONST(c, (PyObject*)co); - ADDOP_LOAD_CONST(c, qualname); - ADDOP_I(c, MAKE_FUNCTION, flags); + 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) { + printf("lookup %s in %s %d %d\n" + "freevars of %s: %s\n", + PyString_AS_STRING(PyObject_Repr(name)), + PyString_AS_STRING(c->u->u_name), + reftype, arg, + PyString_AS_STRING(co->co_name), + PyString_AS_STRING(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; } @@ -1965,598 +1325,148 @@ compiler_decorators(struct compiler *c, asdl_seq* decos) } static int -compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, - asdl_seq *kw_defaults) +compiler_arguments(struct compiler *c, arguments_ty args) { - /* Push a dict of keyword-only default values. - - Return 0 on error, -1 if no dict pushed, 1 if a dict is pushed. - */ int i; - PyObject *keys = NULL; - - 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_) { - PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg); - if (!mangled) { - goto error; - } - if (keys == NULL) { - keys = PyList_New(1); - if (keys == NULL) { - Py_DECREF(mangled); - return 0; - } - PyList_SET_ITEM(keys, 0, mangled); - } - else { - int res = PyList_Append(keys, mangled); - Py_DECREF(mangled); - if (res == -1) { - goto error; - } + int n = asdl_seq_LEN(args->args); + /* Correctly handle nested argument lists */ + for (i = 0; i < n; i++) { + expr_ty arg = (expr_ty)asdl_seq_GET(args->args, i); + if (arg->kind == Tuple_kind) { + PyObject *id = PyString_FromFormat(".%d", i); + if (id == NULL) { + return 0; } - if (!compiler_visit_expr(c, default_)) { - goto error; + if (!compiler_nameop(c, id, Load)) { + Py_DECREF(id); + return 0; } + Py_DECREF(id); + VISIT(c, expr, arg); } } - if (keys != NULL) { - Py_ssize_t default_count = PyList_GET_SIZE(keys); - PyObject *keys_tuple = PyList_AsTuple(keys); - Py_DECREF(keys); - ADDOP_LOAD_CONST_NEW(c, keys_tuple); - ADDOP_I(c, BUILD_CONST_KEY_MAP, default_count); - assert(default_count > 0); - return 1; - } - else { - return -1; - } - -error: - Py_XDECREF(keys); - return 0; -} - -static int -compiler_visit_annexpr(struct compiler *c, expr_ty annotation) -{ - ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation)); return 1; } static int -compiler_visit_argannotation(struct compiler *c, identifier id, - expr_ty annotation, PyObject *names) -{ - if (annotation) { - PyObject *mangled; - if (c->c_future->ff_features & CO_FUTURE_ANNOTATIONS) { - VISIT(c, annexpr, annotation) - } - else { - VISIT(c, expr, annotation); - } - mangled = _Py_Mangle(c->u->u_private, id); - if (!mangled) - return 0; - if (PyList_Append(names, mangled) < 0) { - Py_DECREF(mangled); - return 0; - } - Py_DECREF(mangled); - } - return 1; -} - -static int -compiler_visit_argannotations(struct compiler *c, asdl_seq* args, - PyObject *names) -{ - int i; - for (i = 0; i < asdl_seq_LEN(args); i++) { - arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - if (!compiler_visit_argannotation( - c, - arg->arg, - arg->annotation, - names)) - return 0; - } - return 1; -} - -static int -compiler_visit_annotations(struct compiler *c, arguments_ty args, - expr_ty returns) -{ - /* Push arg annotation dict. - The expressions are evaluated out-of-order wrt the source code. - - Return 0 on error, -1 if no dict pushed, 1 if a dict is pushed. - */ - static identifier return_str; - PyObject *names; - Py_ssize_t len; - names = PyList_New(0); - if (!names) - return 0; - - if (!compiler_visit_argannotations(c, args->args, names)) - goto error; - if (!compiler_visit_argannotations(c, args->posonlyargs, names)) - goto error; - if (args->vararg && args->vararg->annotation && - !compiler_visit_argannotation(c, args->vararg->arg, - args->vararg->annotation, names)) - goto error; - if (!compiler_visit_argannotations(c, args->kwonlyargs, names)) - goto error; - if (args->kwarg && args->kwarg->annotation && - !compiler_visit_argannotation(c, args->kwarg->arg, - args->kwarg->annotation, 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) { - PyObject *keytuple = PyList_AsTuple(names); - Py_DECREF(names); - ADDOP_LOAD_CONST_NEW(c, keytuple); - ADDOP_I(c, BUILD_CONST_KEY_MAP, len); - return 1; - } - else { - Py_DECREF(names); - return -1; - } - -error: - Py_DECREF(names); - return 0; -} - -static int -compiler_visit_defaults(struct compiler *c, arguments_ty args) -{ - VISIT_SEQ(c, expr, args->defaults); - ADDOP_I(c, BUILD_TUPLE, asdl_seq_LEN(args->defaults)); - return 1; -} - -static Py_ssize_t -compiler_default_arguments(struct compiler *c, arguments_ty args) -{ - Py_ssize_t funcflags = 0; - if (args->defaults && asdl_seq_LEN(args->defaults) > 0) { - if (!compiler_visit_defaults(c, args)) - return -1; - funcflags |= 0x01; - } - if (args->kwonlyargs) { - int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, - args->kw_defaults); - if (res == 0) { - return -1; - } - else if (res > 0) { - funcflags |= 0x02; - } - } - return funcflags; -} - -static int -compiler_function(struct compiler *c, stmt_ty s, int is_async) +compiler_function(struct compiler *c, stmt_ty s) { PyCodeObject *co; - PyObject *qualname, *docstring = NULL; - arguments_ty args; - expr_ty returns; - identifier name; - asdl_seq* decos; - asdl_seq *body; - Py_ssize_t i, funcflags; - int annotations; - int scope_type; - int firstlineno; - - if (is_async) { - assert(s->kind == AsyncFunctionDef_kind); - - args = s->v.AsyncFunctionDef.args; - returns = s->v.AsyncFunctionDef.returns; - decos = s->v.AsyncFunctionDef.decorator_list; - name = s->v.AsyncFunctionDef.name; - body = s->v.AsyncFunctionDef.body; - - scope_type = COMPILER_SCOPE_ASYNC_FUNCTION; - } else { - assert(s->kind == FunctionDef_kind); - - args = s->v.FunctionDef.args; - returns = s->v.FunctionDef.returns; - decos = s->v.FunctionDef.decorator_list; - name = s->v.FunctionDef.name; - body = s->v.FunctionDef.body; + PyObject *first_const = Py_None; + arguments_ty args = s->v.FunctionDef.args; + asdl_seq* decos = s->v.FunctionDef.decorator_list; + stmt_ty st; + int i, n, docstring; - scope_type = COMPILER_SCOPE_FUNCTION; - } + assert(s->kind == FunctionDef_kind); if (!compiler_decorators(c, decos)) return 0; - - firstlineno = s->lineno; - if (asdl_seq_LEN(decos)) { - firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno; - } - - funcflags = compiler_default_arguments(c, args); - if (funcflags == -1) { - return 0; - } - - annotations = compiler_visit_annotations(c, args, returns); - if (annotations == 0) { - return 0; - } - else if (annotations > 0) { - funcflags |= 0x04; - } - - if (!compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno)) { + if (args->defaults) + VISIT_SEQ(c, expr, args->defaults); + if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, + s->lineno)) return 0; - } - /* if not -OO mode, add docstring */ - if (c->c_optimize < 2) { - docstring = _PyAST_GetDocString(body); - } - if (compiler_add_const(c, docstring ? docstring : Py_None) < 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; } + /* unpack nested arguments */ + compiler_arguments(c, args); + c->u->u_argcount = asdl_seq_LEN(args->args); - c->u->u_posonlyargcount = asdl_seq_LEN(args->posonlyargs); - c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - VISIT_SEQ_IN_SCOPE(c, stmt, body); + 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); - qualname = c->u->u_qualname; - Py_INCREF(qualname); compiler_exit_scope(c); - if (co == NULL) { - Py_XDECREF(qualname); - Py_XDECREF(co); + if (co == NULL) return 0; - } - compiler_make_closure(c, co, funcflags, qualname); - Py_DECREF(qualname); + compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); Py_DECREF(co); - /* decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); } - return compiler_nameop(c, name, Store); + return compiler_nameop(c, s->v.FunctionDef.name, Store); } static int compiler_class(struct compiler *c, stmt_ty s) { + int n, i; PyCodeObject *co; PyObject *str; - int i, firstlineno; asdl_seq* decos = s->v.ClassDef.decorator_list; if (!compiler_decorators(c, decos)) return 0; - firstlineno = s->lineno; - if (asdl_seq_LEN(decos)) { - firstlineno = ((expr_ty)asdl_seq_GET(decos, 0))->lineno; - } - - /* ultimately generate code for: - <name> = __build_class__(<func>, <name>, *<bases>, **<keywords>) - where: - <func> 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 - <name> is the class name - <bases> is the positional arguments and *varargs argument - <keywords> is the keyword arguments and **kwds argument - This borrows from compiler_call. - */ + /* push class name on stack, needed by BUILD_CLASS */ + ADDOP_O(c, LOAD_CONST, s->v.ClassDef.name, consts); + /* push the tuple of base classes on the stack */ + n = asdl_seq_LEN(s->v.ClassDef.bases); + if (n > 0) + VISIT_SEQ(c, expr, s->v.ClassDef.bases); + ADDOP_I(c, BUILD_TUPLE, n); + if (!compiler_enter_scope(c, s->v.ClassDef.name, (void *)s, + s->lineno)) + return 0; + Py_INCREF(s->v.ClassDef.name); + Py_XSETREF(c->u->u_private, s->v.ClassDef.name); + str = PyString_InternFromString("__name__"); + if (!str || !compiler_nameop(c, str, Load)) { + Py_XDECREF(str); + compiler_exit_scope(c); + return 0; + } - /* 1. compile the class body into a code object */ - if (!compiler_enter_scope(c, s->v.ClassDef.name, - COMPILER_SCOPE_CLASS, (void *)s, firstlineno)) + Py_DECREF(str); + str = PyString_InternFromString("__module__"); + if (!str || !compiler_nameop(c, str, Store)) { + Py_XDECREF(str); + compiler_exit_scope(c); 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_XSETREF(c->u->u_private, s->v.ClassDef.name); - /* 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); - assert(c->u->u_qualname); - ADDOP_LOAD_CONST(c, c->u->u_qualname); - str = PyUnicode_InternFromString("__qualname__"); - 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 __classcell__ if it is referenced, otherwise return None */ - if (c->u->u_ste->ste_needs_class_closure) { - /* Store __classcell__ into class namespace & return it */ - 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 < 0) { - compiler_exit_scope(c); - return 0; - } - assert(i == 0); + } + Py_DECREF(str); - ADDOP_I(c, LOAD_CLOSURE, i); - ADDOP(c, DUP_TOP); - str = PyUnicode_InternFromString("__classcell__"); - if (!str || !compiler_nameop(c, str, Store)) { - Py_XDECREF(str); - compiler_exit_scope(c); - return 0; - } - Py_DECREF(str); - } - else { - /* No methods referenced __class__, so just return None */ - assert(PyDict_GET_SIZE(c->u->u_cellvars) == 0); - ADDOP_LOAD_CONST(c, Py_None); - } - ADDOP_IN_SCOPE(c, RETURN_VALUE); - /* create the code object */ - co = assemble(c, 1); + if (!compiler_body(c, s->v.ClassDef.body)) { + compiler_exit_scope(c); + return 0; } - /* leave the new scope */ + + ADDOP_IN_SCOPE(c, LOAD_LOCALS); + ADDOP_IN_SCOPE(c, RETURN_VALUE); + co = assemble(c, 1); 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, NULL); + compiler_make_closure(c, co, 0); Py_DECREF(co); - /* 4. load class name */ - ADDOP_LOAD_CONST(c, s->v.ClassDef.name); - - /* 5. generate the rest of the code for the call */ - if (!compiler_call_helper(c, 2, - s->v.ClassDef.bases, - s->v.ClassDef.keywords)) - return 0; - - /* 6. apply decorators */ + ADDOP_I(c, CALL_FUNCTION, 0); + ADDOP(c, BUILD_CLASS); + /* apply decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); } - - /* 7. store into <name> */ if (!compiler_nameop(c, s->v.ClassDef.name, Store)) return 0; return 1; } -/* Return 0 if the expression is a constant value except named singletons. - Return 1 otherwise. */ -static int -check_is_arg(expr_ty e) -{ - if (e->kind != Constant_kind) { - return 1; - } - PyObject *value = e->v.Constant.value; - return (value == Py_None - || value == Py_False - || value == Py_True - || value == Py_Ellipsis); -} - -/* Check operands of identity chacks ("is" and "is not"). - Emit a warning if any operand is a constant except named singletons. - Return 0 on error. - */ -static int -check_compare(struct compiler *c, expr_ty e) -{ - Py_ssize_t i, n; - int left = check_is_arg(e->v.Compare.left); - n = asdl_seq_LEN(e->v.Compare.ops); - for (i = 0; i < n; i++) { - cmpop_ty op = (cmpop_ty)asdl_seq_GET(e->v.Compare.ops, i); - int right = check_is_arg((expr_ty)asdl_seq_GET(e->v.Compare.comparators, i)); - if (op == Is || op == IsNot) { - if (!right || !left) { - const char *msg = (op == Is) - ? "\"is\" with a literal. Did you mean \"==\"?" - : "\"is not\" with a literal. Did you mean \"!=\"?"; - return compiler_warn(c, msg); - } - } - left = right; - } - return 1; -} - -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; - } -} - -static int -compiler_jump_if(struct compiler *c, expr_ty e, basicblock *next, int cond) -{ - switch (e->kind) { - case UnaryOp_kind: - if (e->v.UnaryOp.op == Not) - return compiler_jump_if(c, e->v.UnaryOp.operand, next, !cond); - /* fallback to general implementation */ - break; - case BoolOp_kind: { - asdl_seq *s = e->v.BoolOp.values; - Py_ssize_t i, n = asdl_seq_LEN(s) - 1; - assert(n >= 0); - int cond2 = e->v.BoolOp.op == Or; - basicblock *next2 = next; - if (!cond2 != !cond) { - next2 = compiler_new_block(c); - if (next2 == NULL) - return 0; - } - for (i = 0; i < n; ++i) { - if (!compiler_jump_if(c, (expr_ty)asdl_seq_GET(s, i), next2, cond2)) - return 0; - } - if (!compiler_jump_if(c, (expr_ty)asdl_seq_GET(s, n), next, cond)) - return 0; - if (next2 != next) - compiler_use_next_block(c, next2); - return 1; - } - case IfExp_kind: { - basicblock *end, *next2; - end = compiler_new_block(c); - if (end == NULL) - return 0; - next2 = compiler_new_block(c); - if (next2 == NULL) - return 0; - if (!compiler_jump_if(c, e->v.IfExp.test, next2, 0)) - return 0; - if (!compiler_jump_if(c, e->v.IfExp.body, next, cond)) - return 0; - ADDOP_JREL(c, JUMP_FORWARD, end); - compiler_use_next_block(c, next2); - if (!compiler_jump_if(c, e->v.IfExp.orelse, next, cond)) - return 0; - compiler_use_next_block(c, end); - return 1; - } - case Compare_kind: { - Py_ssize_t i, n = asdl_seq_LEN(e->v.Compare.ops) - 1; - if (n > 0) { - if (!check_compare(c, e)) { - return 0; - } - basicblock *cleanup = compiler_new_block(c); - if (cleanup == NULL) - return 0; - VISIT(c, expr, e->v.Compare.left); - for (i = 0; i < n; i++) { - VISIT(c, expr, - (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 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)))); - ADDOP_JABS(c, POP_JUMP_IF_FALSE, cleanup); - NEXT_BLOCK(c); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n)))); - ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); - 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, POP_TOP); - if (!cond) { - ADDOP_JREL(c, JUMP_FORWARD, next); - } - compiler_use_next_block(c, end); - return 1; - } - /* fallback to general implementation */ - break; - } - default: - /* fallback to general implementation */ - break; - } - - /* general implementation */ - VISIT(c, expr, e); - ADDOP_JABS(c, cond ? POP_JUMP_IF_TRUE : POP_JUMP_IF_FALSE, next); - return 1; -} - static int compiler_ifexp(struct compiler *c, expr_ty e) { @@ -2569,8 +1479,8 @@ compiler_ifexp(struct compiler *c, expr_ty e) next = compiler_new_block(c); if (next == NULL) return 0; - if (!compiler_jump_if(c, e->v.IfExp.test, next, 0)) - 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); @@ -2583,57 +1493,86 @@ static int compiler_lambda(struct compiler *c, expr_ty e) { PyCodeObject *co; - PyObject *qualname; static identifier name; - Py_ssize_t funcflags; arguments_ty args = e->v.Lambda.args; assert(e->kind == Lambda_kind); if (!name) { - name = PyUnicode_InternFromString("<lambda>"); + name = PyString_InternFromString("<lambda>"); if (!name) return 0; } - funcflags = compiler_default_arguments(c, args); - if (funcflags == -1) { + if (args->defaults) + VISIT_SEQ(c, expr, args->defaults); + if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) return 0; - } - if (!compiler_enter_scope(c, name, COMPILER_SCOPE_LAMBDA, - (void *)e, e->lineno)) - return 0; + /* unpack nested arguments */ + compiler_arguments(c, args); /* Make None the first constant, so the lambda can't have a docstring. */ - if (compiler_add_const(c, Py_None) < 0) + 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_posonlyargcount = asdl_seq_LEN(args->posonlyargs); - 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) { - co = assemble(c, 0); + ADDOP_IN_SCOPE(c, POP_TOP); } else { ADDOP_IN_SCOPE(c, RETURN_VALUE); - co = assemble(c, 1); } - qualname = c->u->u_qualname; - Py_INCREF(qualname); + co = assemble(c, 1); compiler_exit_scope(c); if (co == NULL) return 0; - compiler_make_closure(c, co, funcflags, qualname); - Py_DECREF(qualname); + compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); Py_DECREF(co); return 1; } static int +compiler_print(struct compiler *c, stmt_ty s) +{ + int i, n; + bool dest; + + assert(s->kind == Print_kind); + n = asdl_seq_LEN(s->v.Print.values); + dest = false; + if (s->v.Print.dest) { + VISIT(c, expr, s->v.Print.dest); + dest = true; + } + for (i = 0; i < n; i++) { + expr_ty e = (expr_ty)asdl_seq_GET(s->v.Print.values, i); + if (dest) { + ADDOP(c, DUP_TOP); + VISIT(c, expr, e); + ADDOP(c, ROT_TWO); + ADDOP(c, PRINT_ITEM_TO); + } + else { + VISIT(c, expr, e); + ADDOP(c, PRINT_ITEM); + } + } + if (s->v.Print.nl) { + if (dest) + ADDOP(c, PRINT_NEWLINE_TO) + else + ADDOP(c, PRINT_NEWLINE) + } + else if (dest) + ADDOP(c, POP_TOP); + return 1; +} + +static int compiler_if(struct compiler *c, stmt_ty s) { basicblock *end, *next; @@ -2648,34 +1587,23 @@ compiler_if(struct compiler *c, stmt_ty s) * constant = 1: "if 1", "if 2", ... * constant = -1: rest */ if (constant == 0) { - BEGIN_DO_NOT_EMIT_BYTECODE - VISIT_SEQ(c, stmt, s->v.If.body); - END_DO_NOT_EMIT_BYTECODE - if (s->v.If.orelse) { + 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); - if (s->v.If.orelse) { - BEGIN_DO_NOT_EMIT_BYTECODE - VISIT_SEQ(c, stmt, s->v.If.orelse); - END_DO_NOT_EMIT_BYTECODE - } } else { - if (asdl_seq_LEN(s->v.If.orelse)) { + if (s->v.If.orelse) { next = compiler_new_block(c); if (next == NULL) return 0; } - else { + else next = end; - } - if (!compiler_jump_if(c, s->v.If.test, next, 0)) { - return 0; - } + VISIT(c, expr, s->v.If.test); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, next); VISIT_SEQ(c, stmt, s->v.If.body); - if (asdl_seq_LEN(s->v.If.orelse)) { - ADDOP_JREL(c, JUMP_FORWARD, end); + 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); } @@ -2692,12 +1620,11 @@ compiler_for(struct compiler *c, stmt_ty s) start = compiler_new_block(c); cleanup = compiler_new_block(c); end = compiler_new_block(c); - if (start == NULL || end == NULL || cleanup == NULL) { + if (start == NULL || end == NULL || cleanup == NULL) return 0; - } - if (!compiler_push_fblock(c, FOR_LOOP, start, end, NULL)) { + 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); @@ -2706,62 +1633,10 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.For.body); ADDOP_JABS(c, JUMP_ABSOLUTE, start); compiler_use_next_block(c, cleanup); - - compiler_pop_fblock(c, FOR_LOOP, start); - - VISIT_SEQ(c, stmt, s->v.For.orelse); - compiler_use_next_block(c, end); - return 1; -} - - -static int -compiler_async_for(struct compiler *c, stmt_ty s) -{ - basicblock *start, *except, *end; - if (c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT){ - c->u->u_ste->ste_coroutine = 1; - } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION) { - return compiler_error(c, "'async for' outside async function"); - } - - start = compiler_new_block(c); - except = compiler_new_block(c); - end = compiler_new_block(c); - - if (start == NULL || except == NULL || end == NULL) { - return 0; - } - VISIT(c, expr, s->v.AsyncFor.iter); - ADDOP(c, GET_AITER); - - compiler_use_next_block(c, start); - if (!compiler_push_fblock(c, FOR_LOOP, start, end, NULL)) { - return 0; - } - /* SETUP_FINALLY to guard the __anext__ call */ - ADDOP_JREL(c, SETUP_FINALLY, except); - ADDOP(c, GET_ANEXT); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - ADDOP(c, POP_BLOCK); /* for SETUP_FINALLY */ - - /* Success block for __anext__ */ - VISIT(c, expr, s->v.AsyncFor.target); - VISIT_SEQ(c, stmt, s->v.AsyncFor.body); - ADDOP_JABS(c, JUMP_ABSOLUTE, start); - - compiler_pop_fblock(c, FOR_LOOP, start); - - /* Except block for __anext__ */ - compiler_use_next_block(c, except); - ADDOP(c, END_ASYNC_FOR); - - /* `else` block */ + 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; } @@ -2772,20 +1647,8 @@ compiler_while(struct compiler *c, stmt_ty s) int constant = expr_constant(s->v.While.test); if (constant == 0) { - BEGIN_DO_NOT_EMIT_BYTECODE - // Push a dummy block so the VISIT_SEQ knows that we are - // inside a while loop so it can correctly evaluate syntax - // errors. - if (!compiler_push_fblock(c, WHILE_LOOP, NULL, NULL, NULL)) { - return 0; - } - VISIT_SEQ(c, stmt, s->v.While.body); - // Remove the dummy block now that is not needed. - compiler_pop_fblock(c, WHILE_LOOP, NULL); - END_DO_NOT_EMIT_BYTECODE - if (s->v.While.orelse) { + if (s->v.While.orelse) VISIT_SEQ(c, stmt, s->v.While.orelse); - } return 1; } loop = compiler_new_block(c); @@ -2805,12 +1668,13 @@ compiler_while(struct compiler *c, stmt_ty s) else orelse = NULL; + ADDOP_JREL(c, SETUP_LOOP, end); compiler_use_next_block(c, loop); - if (!compiler_push_fblock(c, WHILE_LOOP, loop, end, NULL)) + if (!compiler_push_fblock(c, LOOP, loop)) return 0; if (constant == -1) { - if (!compiler_jump_if(c, s->v.While.test, anchor, 0)) - return 0; + 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); @@ -2821,8 +1685,8 @@ compiler_while(struct compiler *c, stmt_ty s) if (constant == -1) compiler_use_next_block(c, anchor); - compiler_pop_fblock(c, WHILE_LOOP, loop); - + 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); @@ -2831,76 +1695,47 @@ compiler_while(struct compiler *c, stmt_ty s) } static int -compiler_return(struct compiler *c, stmt_ty s) +compiler_continue(struct compiler *c) { - int preserve_tos = ((s->v.Return.value != NULL) && - (s->v.Return.value->kind != Constant_kind)); - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'return' outside function"); - if (s->v.Return.value != NULL && - c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator) - { - return compiler_error( - c, "'return' with value in async generator"); - } - if (preserve_tos) { - VISIT(c, expr, s->v.Return.value); - } - if (!compiler_unwind_fblock_stack(c, preserve_tos, NULL)) - return 0; - if (s->v.Return.value == NULL) { - ADDOP_LOAD_CONST(c, Py_None); - } - else if (!preserve_tos) { - VISIT(c, expr, s->v.Return.value); - } - ADDOP(c, RETURN_VALUE); - - 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; -static int -compiler_break(struct compiler *c) -{ - struct fblockinfo *loop = NULL; - if (!compiler_unwind_fblock_stack(c, 0, &loop)) { - return 0; - } - if (loop == NULL) { - return compiler_error(c, "'break' outside loop"); - } - if (!compiler_unwind_fblock(c, loop, 0)) { - return 0; + 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); } - ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_exit); - return 1; -} -static int -compiler_continue(struct compiler *c) -{ - struct fblockinfo *loop = NULL; - if (!compiler_unwind_fblock_stack(c, 0, &loop)) { - return 0; - } - if (loop == NULL) { - return compiler_error(c, "'continue' not properly in loop"); - } - ADDOP_JABS(c, JUMP_ABSOLUTE, loop->fb_block); return 1; } - /* Code generated for "try: <body> finally: <finalbody>" is as follows: SETUP_FINALLY L <code for body> POP_BLOCK - <code for finalbody> - JUMP E - L: - <code for finalbody> - E: + LOAD_CONST <None> + L: <code for finalbody> + END_FINALLY The special instructions use the block stack. Each block stack entry contains the instruction that created it (here @@ -2911,61 +1746,57 @@ compiler_continue(struct compiler *c) Pushes the current value stack level and the label onto the block stack. POP_BLOCK: - Pops en entry from the block stack. + 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. The block stack is unwound when an exception is raised: - when a SETUP_FINALLY entry is found, the raised and the caught - exceptions are pushed onto the value stack (and the exception - condition is cleared), and the interpreter jumps to the label - gotten from the block stack. + when a SETUP_FINALLY entry is found, the exception is pushed + onto the value stack (and the exception condition is cleared), + and the interpreter jumps to the label gotten from the block + stack. */ static int compiler_try_finally(struct compiler *c, stmt_ty s) { - basicblock *body, *end, *exit; - + basicblock *body, *end; body = compiler_new_block(c); end = compiler_new_block(c); - exit = compiler_new_block(c); - if (body == NULL || end == NULL || exit == NULL) + if (body == NULL || end == NULL) return 0; - /* `try` block */ ADDOP_JREL(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, FINALLY_TRY, body, end, s->v.Try.finalbody)) + if (!compiler_push_fblock(c, FINALLY_TRY, body)) return 0; - if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { - if (!compiler_try_except(c, s)) - return 0; - } - else { - VISIT_SEQ(c, stmt, s->v.Try.body); - } + VISIT_SEQ(c, stmt, s->v.TryFinally.body); ADDOP(c, POP_BLOCK); compiler_pop_fblock(c, FINALLY_TRY, body); - VISIT_SEQ(c, stmt, s->v.Try.finalbody); - ADDOP_JREL(c, JUMP_FORWARD, exit); - /* `finally` block */ + + ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, end); - if (!compiler_push_fblock(c, FINALLY_END, end, NULL, NULL)) + if (!compiler_push_fblock(c, FINALLY_END, end)) return 0; - VISIT_SEQ(c, stmt, s->v.Try.finalbody); + VISIT_SEQ(c, stmt, s->v.TryFinally.finalbody); + ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, end); - ADDOP(c, RERAISE); - compiler_use_next_block(c, exit); + return 1; } /* - Code generated for "try: S except E1 as V1: S1 except E2 as V2: S2 ...": + Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...": (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_FINALLY L1 + [] SETUP_EXCEPT L1 [] <code for S> [] POP_BLOCK [] JUMP_FORWARD L0 @@ -2983,7 +1814,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) [tb, val, exc] L2: DUP .............................etc....................... - [tb, val, exc] Ln+1: RERAISE # re-raise exception + [tb, val, exc] Ln+1: END_FINALLY # re-raise exception [] L0: <next statement> @@ -2993,7 +1824,7 @@ static int compiler_try_except(struct compiler *c, stmt_ty s) { basicblock *body, *orelse, *except, *end; - Py_ssize_t i, n; + int i, n; body = compiler_new_block(c); except = compiler_new_block(c); @@ -3001,24 +1832,23 @@ compiler_try_except(struct compiler *c, stmt_ty s) end = compiler_new_block(c); if (body == NULL || except == NULL || orelse == NULL || end == NULL) return 0; - ADDOP_JREL(c, SETUP_FINALLY, except); + ADDOP_JREL(c, SETUP_EXCEPT, except); compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, EXCEPT, body, NULL, NULL)) + if (!compiler_push_fblock(c, EXCEPT, body)) return 0; - VISIT_SEQ(c, stmt, s->v.Try.body); + 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.Try.handlers); + 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.Try.handlers, i); + 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_set = false; c->u->u_lineno = handler->lineno; - c->u->u_col_offset = handler->col_offset; except = compiler_new_block(c); if (except == NULL) return 0; @@ -3030,126 +1860,48 @@ compiler_try_except(struct compiler *c, stmt_ty s) } 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 == NULL || cleanup_body == NULL) { - return 0; - } - - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); - - /* - try: - # body - except type as name: - try: - # body - finally: - name = None # in case body contains "del name" - del name - */ - - /* second try: */ - ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); - compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, handler->v.ExceptHandler.name)) - return 0; - - /* second # body */ - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); - ADDOP(c, POP_BLOCK); - ADDOP(c, POP_EXCEPT); - /* name = None; del name */ - ADDOP_LOAD_CONST(c, Py_None); - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - compiler_nameop(c, handler->v.ExceptHandler.name, Del); - ADDOP_JREL(c, JUMP_FORWARD, end); - - /* except: */ - compiler_use_next_block(c, cleanup_end); - - /* name = None; del name */ - ADDOP_LOAD_CONST(c, Py_None); - compiler_nameop(c, handler->v.ExceptHandler.name, Store); - compiler_nameop(c, handler->v.ExceptHandler.name, Del); - - ADDOP(c, RERAISE); + VISIT(c, expr, handler->v.ExceptHandler.name); } else { - basicblock *cleanup_body; - - 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, HANDLER_CLEANUP, cleanup_body, NULL, NULL)) - return 0; - VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); - compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); - ADDOP(c, POP_EXCEPT); - ADDOP_JREL(c, JUMP_FORWARD, end); } + ADDOP(c, POP_TOP); + VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); + ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, except); } - ADDOP(c, RERAISE); + ADDOP(c, END_FINALLY); compiler_use_next_block(c, orelse); - VISIT_SEQ(c, stmt, s->v.Try.orelse); + VISIT_SEQ(c, stmt, s->v.TryExcept.orelse); compiler_use_next_block(c, end); return 1; } static int -compiler_try(struct compiler *c, stmt_ty s) { - if (s->v.Try.finalbody && asdl_seq_LEN(s->v.Try.finalbody)) - return compiler_try_finally(c, s); - else - return compiler_try_except(c, s); -} - - -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 - IMPORT_FROM for each name. + LOAD_ATTR for each name. */ - Py_ssize_t len = PyUnicode_GET_LENGTH(name); - Py_ssize_t dot = PyUnicode_FindChar(name, '.', 0, len, 1); - if (dot == -2) - return 0; - if (dot != -1) { + const char *src = PyString_AS_STRING(name); + const char *dot = strchr(src, '.'); + if (dot) { /* Consume the base module name to get the first attribute */ - while (1) { - Py_ssize_t pos = dot + 1; + src = dot + 1; + while (dot) { + /* NB src is only defined when dot != NULL */ PyObject *attr; - dot = PyUnicode_FindChar(name, '.', pos, len, 1); - if (dot == -2) - return 0; - attr = PyUnicode_Substring(name, pos, (dot != -1) ? dot : len); + dot = strchr(src, '.'); + attr = PyString_FromStringAndSize(src, + dot ? dot - src : strlen(src)); if (!attr) return 0; - ADDOP_N(c, IMPORT_FROM, attr, names); - if (dot == -1) { - break; - } - ADDOP(c, ROT_TWO); - ADDOP(c, POP_TOP); - } - if (!compiler_nameop(c, asname, Store)) { - return 0; + ADDOP_N(c, LOAD_ATTR, attr, names); + src = dot + 1; } - ADDOP(c, POP_TOP); - return 1; } return compiler_nameop(c, asname, Store); } @@ -3164,14 +1916,23 @@ compiler_import(struct compiler *c, stmt_ty s) module names. XXX Perhaps change the representation to make this case simpler? */ - Py_ssize_t i, n = asdl_seq_LEN(s->v.Import.names); + 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; + + if (c->c_flags && (c->c_flags->cf_flags & CO_FUTURE_ABSOLUTE_IMPORT)) + level = PyInt_FromLong(0); + else + level = PyInt_FromLong(-1); + + if (level == NULL) + return 0; - ADDOP_LOAD_CONST(c, _PyLong_Zero); - ADDOP_LOAD_CONST(c, Py_None); + ADDOP_N(c, LOAD_CONST, level, consts); + ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP_NAME(c, IMPORT_NAME, alias->name, names); if (alias->asname) { @@ -3181,15 +1942,16 @@ compiler_import(struct compiler *c, stmt_ty s) } else { identifier tmp = alias->name; - Py_ssize_t dot = PyUnicode_FindChar( - alias->name, '.', 0, PyUnicode_GET_LENGTH(alias->name), 1); - if (dot != -1) { - tmp = PyUnicode_Substring(alias->name, 0, dot); + const char *base = PyString_AS_STRING(alias->name); + char *dot = strchr(base, '.'); + if (dot) { + tmp = PyString_FromStringAndSize(base, + dot - base); if (tmp == NULL) return 0; } r = compiler_nameop(c, tmp, Store); - if (dot != -1) { + if (dot) { Py_DECREF(tmp); } if (!r) @@ -3202,17 +1964,27 @@ compiler_import(struct compiler *c, stmt_ty s) static int compiler_from_import(struct compiler *c, stmt_ty s) { - Py_ssize_t i, n = asdl_seq_LEN(s->v.ImportFrom.names); - PyObject *names; + int i, n = asdl_seq_LEN(s->v.ImportFrom.names); + + PyObject *level, *names; static PyObject *empty_string; if (!empty_string) { - empty_string = PyUnicode_FromString(""); + empty_string = PyString_FromString(""); if (!empty_string) return 0; } - ADDOP_LOAD_CONST_NEW(c, PyLong_FromLong(s->v.ImportFrom.level)); + if (s->v.ImportFrom.level == 0 && c->c_flags && + !(c->c_flags->cf_flags & CO_FUTURE_ABSOLUTE_IMPORT)) + level = PyInt_FromLong(-1); + else + level = PyInt_FromLong(s->v.ImportFrom.level); + + if (!level) { + return 0; + } + ADDOP_N(c, LOAD_CONST, level, consts); names = PyTuple_New(n); if (!names) @@ -3226,12 +1998,12 @@ compiler_from_import(struct compiler *c, stmt_ty s) } if (s->lineno > c->c_future->ff_lineno && s->v.ImportFrom.module && - _PyUnicode_EqualToASCIIString(s->v.ImportFrom.module, "__future__")) { + !strcmp(PyString_AS_STRING(s->v.ImportFrom.module), "__future__")) { Py_DECREF(names); return compiler_error(c, "from __future__ imports must occur " "at the beginning of the file"); } - ADDOP_LOAD_CONST_NEW(c, names); + ADDOP_N(c, LOAD_CONST, names, consts); if (s->v.ImportFrom.module) { ADDOP_NAME(c, IMPORT_NAME, s->v.ImportFrom.module, names); @@ -3243,7 +2015,7 @@ compiler_from_import(struct compiler *c, stmt_ty s) alias_ty alias = (alias_ty)asdl_seq_GET(s->v.ImportFrom.names, i); identifier store_name; - if (i == 0 && PyUnicode_READ_CHAR(alias->name, 0) == '*') { + if (i == 0 && *PyString_AS_STRING(alias->name) == '*') { assert(n == 1); ADDOP(c, IMPORT_STAR); return 1; @@ -3266,25 +2038,30 @@ compiler_from_import(struct compiler *c, stmt_ty s) static int compiler_assert(struct compiler *c, stmt_ty s) { + static PyObject *assertion_error = NULL; basicblock *end; - if (c->c_optimize) + if (Py_OptimizeFlag) return 1; + if (assertion_error == NULL) { + assertion_error = PyString_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) - { - if (!compiler_warn(c, "assertion is always true, " - "perhaps remove parentheses?")) - { + 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; - if (!compiler_jump_if(c, s->v.Assert.test, end, 1)) - return 0; - ADDOP(c, LOAD_ASSERTION_ERROR); + 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); @@ -3295,41 +2072,29 @@ compiler_assert(struct compiler *c, stmt_ty s) } static int -compiler_visit_stmt_expr(struct compiler *c, expr_ty value) -{ - if (c->c_interactive && c->c_nestlevel <= 1) { - VISIT(c, expr, value); - ADDOP(c, PRINT_EXPR); - return 1; - } - - if (value->kind == Constant_kind) { - /* ignore constant statement */ - return 1; - } - - VISIT(c, expr, value); - ADDOP(c, POP_TOP); - return 1; -} - -static int compiler_visit_stmt(struct compiler *c, stmt_ty s) { - Py_ssize_t i, n; + int i, n; /* 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; + c->u->u_lineno_set = false; switch (s->kind) { case FunctionDef_kind: - return compiler_function(c, s, 0); + return compiler_function(c, s); case ClassDef_kind: return compiler_class(c, s); case Return_kind: - return compiler_return(c, s); + 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; @@ -3345,8 +2110,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) break; case AugAssign_kind: return compiler_augassign(c, s); - case AnnAssign_kind: - return compiler_annassign(c, s); + case Print_kind: + return compiler_print(c, s); case For_kind: return compiler_for(c, s); case While_kind: @@ -3355,45 +2120,70 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) return compiler_if(c, s); case Raise_kind: n = 0; - if (s->v.Raise.exc) { - VISIT(c, expr, s->v.Raise.exc); + if (s->v.Raise.type) { + VISIT(c, expr, s->v.Raise.type); n++; - if (s->v.Raise.cause) { - VISIT(c, expr, s->v.Raise.cause); + if (s->v.Raise.inst) { + VISIT(c, expr, s->v.Raise.inst); n++; + if (s->v.Raise.tback) { + VISIT(c, expr, s->v.Raise.tback); + n++; + } } } - ADDOP_I(c, RAISE_VARARGS, (int)n); + ADDOP_I(c, RAISE_VARARGS, n); break; - case Try_kind: - return compiler_try(c, s); + 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 Exec_kind: + VISIT(c, expr, s->v.Exec.body); + if (s->v.Exec.globals) { + VISIT(c, expr, s->v.Exec.globals); + if (s->v.Exec.locals) { + VISIT(c, expr, s->v.Exec.locals); + } else { + ADDOP(c, DUP_TOP); + } + } else { + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, DUP_TOP); + } + ADDOP(c, EXEC_STMT); + break; case Global_kind: - case Nonlocal_kind: break; case Expr_kind: - return compiler_visit_stmt_expr(c, s->v.Expr.value); + 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: - return compiler_break(c); + 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, 0); - case AsyncFunctionDef_kind: - return compiler_function(c, s, 1); - case AsyncWith_kind: - return compiler_async_with(c, s, 0); - case AsyncFor_kind: - return compiler_async_for(c, s); + return compiler_with(c, s); } - return 1; } @@ -3426,10 +2216,11 @@ binop(struct compiler *c, operator_ty op) return BINARY_SUBTRACT; case Mult: return BINARY_MULTIPLY; - case MatMult: - return BINARY_MATRIX_MULTIPLY; case Div: - return BINARY_TRUE_DIVIDE; + if (c->c_flags && c->c_flags->cf_flags & CO_FUTURE_DIVISION) + return BINARY_TRUE_DIVIDE; + else + return BINARY_DIVIDE; case Mod: return BINARY_MODULO; case Pow: @@ -3454,6 +2245,35 @@ binop(struct compiler *c, operator_ty op) } 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; + } +} + +static int inplace_binop(struct compiler *c, operator_ty op) { switch (op) { @@ -3463,10 +2283,11 @@ inplace_binop(struct compiler *c, operator_ty op) return INPLACE_SUBTRACT; case Mult: return INPLACE_MULTIPLY; - case MatMult: - return INPLACE_MATRIX_MULTIPLY; case Div: - return INPLACE_TRUE_DIVIDE; + if (c->c_flags && c->c_flags->cf_flags & CO_FUTURE_DIVISION) + return INPLACE_TRUE_DIVIDE; + else + return INPLACE_DIVIDE; case Mod: return INPLACE_MODULO; case Pow: @@ -3493,18 +2314,13 @@ inplace_binop(struct compiler *c, operator_ty op) static int compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) { - int op, scope; - Py_ssize_t 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! */ - assert(!_PyUnicode_EqualToASCIIString(name, "None") && - !_PyUnicode_EqualToASCIIString(name, "True") && - !_PyUnicode_EqualToASCIIString(name, "False")); - mangled = _Py_Mangle(c->u->u_private, name); if (!mangled) return 0; @@ -3526,7 +2342,8 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) optype = OP_FAST; break; case GLOBAL_IMPLICIT: - if (c->u->u_ste->ste_type == FunctionBlock) + if (c->u->u_ste->ste_type == FunctionBlock && + !c->u->u_ste->ste_unoptimized) optype = OP_GLOBAL; break; case GLOBAL_EXPLICIT: @@ -3538,21 +2355,23 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) } /* XXX Leave assert here, but handle __doc__ and the like better */ - assert(scope || PyUnicode_READ_CHAR(name, 0) == '_'); + assert(scope || PyString_AS_STRING(name)[0] == '_'); switch (optype) { case OP_DEREF: switch (ctx) { - case Load: - op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF; - break; - case Store: - op = STORE_DEREF; - break; + case Load: op = LOAD_DEREF; break; + case Store: op = STORE_DEREF; break; case AugLoad: case AugStore: break; - case Del: op = DELETE_DEREF; break; + case Del: + PyErr_Format(PyExc_SyntaxError, + "can not delete variable '%s' referenced " + "in nested scope", + PyString_AS_STRING(name)); + Py_DECREF(mangled); + return 0; case Param: default: PyErr_SetString(PyExc_SystemError, @@ -3563,9 +2382,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) case OP_FAST: switch (ctx) { case Load: op = LOAD_FAST; break; - case Store: - op = STORE_FAST; - break; + case Store: op = STORE_FAST; break; case Del: op = DELETE_FAST; break; case AugLoad: case AugStore: @@ -3581,9 +2398,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) case OP_GLOBAL: switch (ctx) { case Load: op = LOAD_GLOBAL; break; - case Store: - op = STORE_GLOBAL; - break; + case Store: op = STORE_GLOBAL; break; case Del: op = DELETE_GLOBAL; break; case AugLoad: case AugStore: @@ -3598,9 +2413,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) case OP_NAME: switch (ctx) { case Load: op = LOAD_NAME; break; - case Store: - op = STORE_NAME; - break; + case Store: op = STORE_NAME; break; case Del: op = DELETE_NAME; break; case AugLoad: case AugStore: @@ -3626,8 +2439,7 @@ static int compiler_boolop(struct compiler *c, expr_ty e) { basicblock *end; - int jumpi; - Py_ssize_t i, n; + int jumpi, i, n; asdl_seq *s; assert(e->kind == BoolOp_kind); @@ -3651,207 +2463,29 @@ compiler_boolop(struct compiler *c, expr_ty e) } static int -starunpack_helper(struct compiler *c, asdl_seq *elts, - int single_op, int inner_op, int outer_op) -{ - Py_ssize_t n = asdl_seq_LEN(elts); - Py_ssize_t i, nsubitems = 0, nseen = 0; - if (n > 2 && are_all_items_const(elts, 0, n)) { - PyObject *folded = PyTuple_New(n); - if (folded == NULL) { - return 0; - } - PyObject *val; - for (i = 0; i < n; i++) { - val = ((expr_ty)asdl_seq_GET(elts, i))->v.Constant.value; - Py_INCREF(val); - PyTuple_SET_ITEM(folded, i, val); - } - if (outer_op == BUILD_SET_UNPACK) { - Py_SETREF(folded, PyFrozenSet_New(folded)); - if (folded == NULL) { - return 0; - } - } - ADDOP_LOAD_CONST_NEW(c, folded); - ADDOP_I(c, outer_op, 1); - return 1; - } - for (i = 0; i < n; i++) { - expr_ty elt = asdl_seq_GET(elts, i); - if (elt->kind == Starred_kind) { - if (nseen) { - ADDOP_I(c, inner_op, nseen); - nseen = 0; - nsubitems++; - } - VISIT(c, expr, elt->v.Starred.value); - nsubitems++; - } - else { - VISIT(c, expr, elt); - nseen++; - } - } - if (nsubitems) { - if (nseen) { - ADDOP_I(c, inner_op, nseen); - nsubitems++; - } - ADDOP_I(c, outer_op, nsubitems); - } - else - ADDOP_I(c, single_op, nseen); - return 1; -} - -static int -assignment_helper(struct compiler *c, asdl_seq *elts) -{ - Py_ssize_t n = asdl_seq_LEN(elts); - Py_ssize_t i; - int seen_star = 0; - for (i = 0; i < n; i++) { - expr_ty elt = asdl_seq_GET(elts, i); - if (elt->kind == Starred_kind && !seen_star) { - if ((i >= (1 << 8)) || - (n-i-1 >= (INT_MAX >> 8))) - return compiler_error(c, - "too many expressions in " - "star-unpacking assignment"); - ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); - seen_star = 1; - asdl_seq_SET(elts, i, elt->v.Starred.value); - } - 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, elts); - return 1; -} - -static int compiler_list(struct compiler *c, expr_ty e) { - asdl_seq *elts = e->v.List.elts; + int n = asdl_seq_LEN(e->v.List.elts); if (e->v.List.ctx == Store) { - return assignment_helper(c, elts); + ADDOP_I(c, UNPACK_SEQUENCE, n); } - else if (e->v.List.ctx == Load) { - return starunpack_helper(c, elts, - BUILD_LIST, BUILD_TUPLE, BUILD_LIST_UNPACK); + VISIT_SEQ(c, expr, e->v.List.elts); + if (e->v.List.ctx == Load) { + ADDOP_I(c, BUILD_LIST, n); } - else - VISIT_SEQ(c, expr, elts); return 1; } static int compiler_tuple(struct compiler *c, expr_ty e) { - asdl_seq *elts = e->v.Tuple.elts; + int n = asdl_seq_LEN(e->v.Tuple.elts); if (e->v.Tuple.ctx == Store) { - return assignment_helper(c, elts); - } - else if (e->v.Tuple.ctx == Load) { - return starunpack_helper(c, elts, - BUILD_TUPLE, BUILD_TUPLE, BUILD_TUPLE_UNPACK); - } - else - VISIT_SEQ(c, expr, elts); - return 1; -} - -static int -compiler_set(struct compiler *c, expr_ty e) -{ - return starunpack_helper(c, e->v.Set.elts, BUILD_SET, - BUILD_SET, BUILD_SET_UNPACK); -} - -static int -are_all_items_const(asdl_seq *seq, Py_ssize_t begin, Py_ssize_t end) -{ - Py_ssize_t i; - for (i = begin; i < end; i++) { - expr_ty key = (expr_ty)asdl_seq_GET(seq, i); - if (key == NULL || key->kind != Constant_kind) - return 0; - } - return 1; -} - -static int -compiler_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end) -{ - Py_ssize_t i, n = end - begin; - PyObject *keys, *key; - if (n > 1 && are_all_items_const(e->v.Dict.keys, begin, end)) { - for (i = begin; i < end; i++) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - } - keys = PyTuple_New(n); - if (keys == NULL) { - return 0; - } - for (i = begin; i < end; i++) { - key = ((expr_ty)asdl_seq_GET(e->v.Dict.keys, i))->v.Constant.value; - Py_INCREF(key); - PyTuple_SET_ITEM(keys, i - begin, key); - } - ADDOP_LOAD_CONST_NEW(c, keys); - ADDOP_I(c, BUILD_CONST_KEY_MAP, n); - } - else { - for (i = begin; i < end; i++) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i)); - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - } - ADDOP_I(c, BUILD_MAP, n); - } - return 1; -} - -static int -compiler_dict(struct compiler *c, expr_ty e) -{ - Py_ssize_t i, n, elements; - int containers; - int is_unpacking = 0; - n = asdl_seq_LEN(e->v.Dict.values); - containers = 0; - elements = 0; - for (i = 0; i < n; i++) { - is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL; - if (elements == 0xFFFF || (elements && is_unpacking)) { - if (!compiler_subdict(c, e, i - elements, i)) - return 0; - containers++; - elements = 0; - } - if (is_unpacking) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); - containers++; - } - else { - elements++; - } - } - if (elements || containers == 0) { - if (!compiler_subdict(c, e, n - elements, n)) - return 0; - containers++; + ADDOP_I(c, UNPACK_SEQUENCE, n); } - /* If there is more than one dict, they need to be merged into a new - * dict. If there is one dict and it's an unpacking, then it needs - * to be copied into a new dict." */ - if (containers > 1 || is_unpacking) { - ADDOP_I(c, BUILD_MAP_UNPACK, containers); + VISIT_SEQ(c, expr, e->v.Tuple.elts); + if (e->v.Tuple.ctx == Load) { + ADDOP_I(c, BUILD_TUPLE, n); } return 1; } @@ -3859,36 +2493,36 @@ compiler_dict(struct compiler *c, expr_ty e) static int compiler_compare(struct compiler *c, expr_ty e) { - Py_ssize_t i, n; + int i, n; + basicblock *cleanup = NULL; - if (!check_compare(c, e)) { - return 0; - } + /* XXX the logic can be cleaned up for 1 or multiple comparisons */ VISIT(c, expr, e->v.Compare.left); - assert(asdl_seq_LEN(e->v.Compare.ops) > 0); - n = asdl_seq_LEN(e->v.Compare.ops) - 1; - if (n == 0) { - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, 0)); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, 0)))); - } - else { - basicblock *cleanup = compiler_new_block(c); + n = asdl_seq_LEN(e->v.Compare.ops); + assert(n > 0); + if (n > 1) { + cleanup = compiler_new_block(c); if (cleanup == NULL) return 0; - for (i = 0; i < n; i++) { + 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)); - ADDOP(c, DUP_TOP); - ADDOP(c, ROT_THREE); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, i)))); - ADDOP_JABS(c, JUMP_IF_FALSE_OR_POP, cleanup); - NEXT_BLOCK(c); - } - VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Compare.comparators, n)); - ADDOP_I(c, COMPARE_OP, - cmpop((cmpop_ty)(asdl_seq_GET(e->v.Compare.ops, n)))); + } + 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; @@ -3901,414 +2535,53 @@ compiler_compare(struct compiler *c, expr_ty e) return 1; } -static PyTypeObject * -infer_type(expr_ty e) -{ - switch (e->kind) { - case Tuple_kind: - return &PyTuple_Type; - case List_kind: - case ListComp_kind: - return &PyList_Type; - case Dict_kind: - case DictComp_kind: - return &PyDict_Type; - case Set_kind: - case SetComp_kind: - return &PySet_Type; - case GeneratorExp_kind: - return &PyGen_Type; - case Lambda_kind: - return &PyFunction_Type; - case JoinedStr_kind: - case FormattedValue_kind: - return &PyUnicode_Type; - case Constant_kind: - return e->v.Constant.value->ob_type; - default: - return NULL; - } -} - -static int -check_caller(struct compiler *c, expr_ty e) -{ - switch (e->kind) { - case Constant_kind: - case Tuple_kind: - case List_kind: - case ListComp_kind: - case Dict_kind: - case DictComp_kind: - case Set_kind: - case SetComp_kind: - case GeneratorExp_kind: - case JoinedStr_kind: - case FormattedValue_kind: - return compiler_warn(c, "'%.200s' object is not callable; " - "perhaps you missed a comma?", - infer_type(e)->tp_name); - default: - return 1; - } -} - -static int -check_subscripter(struct compiler *c, expr_ty e) -{ - PyObject *v; - - switch (e->kind) { - case Constant_kind: - v = e->v.Constant.value; - if (!(v == Py_None || v == Py_Ellipsis || - PyLong_Check(v) || PyFloat_Check(v) || PyComplex_Check(v) || - PyAnySet_Check(v))) - { - return 1; - } - /* fall through */ - case Set_kind: - case SetComp_kind: - case GeneratorExp_kind: - case Lambda_kind: - return compiler_warn(c, "'%.200s' object is not subscriptable; " - "perhaps you missed a comma?", - infer_type(e)->tp_name); - default: - return 1; - } -} - -static int -check_index(struct compiler *c, expr_ty e, slice_ty s) -{ - PyObject *v; - - if (s->kind != Index_kind) { - return 1; - } - PyTypeObject *index_type = infer_type(s->v.Index.value); - if (index_type == NULL - || PyType_FastSubclass(index_type, Py_TPFLAGS_LONG_SUBCLASS) - || index_type == &PySlice_Type) { - return 1; - } - - switch (e->kind) { - case Constant_kind: - v = e->v.Constant.value; - if (!(PyUnicode_Check(v) || PyBytes_Check(v) || PyTuple_Check(v))) { - return 1; - } - /* fall through */ - case Tuple_kind: - case List_kind: - case ListComp_kind: - case JoinedStr_kind: - case FormattedValue_kind: - return compiler_warn(c, "%.200s indices must be integers or slices, " - "not %.200s; " - "perhaps you missed a comma?", - infer_type(e)->tp_name, - index_type->tp_name); - default: - return 1; - } -} - -// Return 1 if the method call was optimized, -1 if not, and 0 on error. -static int -maybe_optimize_method_call(struct compiler *c, expr_ty e) -{ - Py_ssize_t argsl, i; - expr_ty meth = e->v.Call.func; - asdl_seq *args = e->v.Call.args; - - /* Check that the call node is an attribute access, and that - the call doesn't have keyword parameters. */ - if (meth->kind != Attribute_kind || meth->v.Attribute.ctx != Load || - asdl_seq_LEN(e->v.Call.keywords)) - return -1; - - /* Check that there are no *varargs types of arguments. */ - argsl = asdl_seq_LEN(args); - for (i = 0; i < argsl; i++) { - expr_ty elt = asdl_seq_GET(args, i); - if (elt->kind == Starred_kind) { - return -1; - } - } - - /* Alright, we can optimize the code. */ - VISIT(c, expr, meth->v.Attribute.value); - ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names); - VISIT_SEQ(c, expr, e->v.Call.args); - ADDOP_I(c, CALL_METHOD, asdl_seq_LEN(e->v.Call.args)); - return 1; -} - static int compiler_call(struct compiler *c, expr_ty e) { - int ret = maybe_optimize_method_call(c, e); - if (ret >= 0) { - return ret; - } - if (!check_caller(c, e->v.Call.func)) { - return 0; - } - VISIT(c, expr, e->v.Call.func); - return compiler_call_helper(c, 0, - e->v.Call.args, - e->v.Call.keywords); -} - -static int -compiler_joined_str(struct compiler *c, expr_ty e) -{ - VISIT_SEQ(c, expr, e->v.JoinedStr.values); - if (asdl_seq_LEN(e->v.JoinedStr.values) != 1) - ADDOP_I(c, BUILD_STRING, asdl_seq_LEN(e->v.JoinedStr.values)); - return 1; -} + int n, code = 0; -/* Used to implement f-strings. Format a single value. */ -static int -compiler_formatted_value(struct compiler *c, expr_ty e) -{ - /* Our oparg encodes 2 pieces of information: the conversion - character, and whether or not a format_spec was provided. - - Convert the conversion char to 3 bits: - : 000 0x0 FVC_NONE The default if nothing specified. - !s : 001 0x1 FVC_STR - !r : 010 0x2 FVC_REPR - !a : 011 0x3 FVC_ASCII - - next bit is whether or not we have a format spec: - yes : 100 0x4 - no : 000 0x0 - */ - - int conversion = e->v.FormattedValue.conversion; - int oparg; - - /* The expression to be formatted. */ - VISIT(c, expr, e->v.FormattedValue.value); - - switch (conversion) { - case 's': oparg = FVC_STR; break; - case 'r': oparg = FVC_REPR; break; - case 'a': oparg = FVC_ASCII; break; - case -1: oparg = FVC_NONE; break; - default: - PyErr_Format(PyExc_SystemError, - "Unrecognized conversion character %d", conversion); - return 0; + VISIT(c, expr, e->v.Call.func); + n = asdl_seq_LEN(e->v.Call.args); + VISIT_SEQ(c, expr, e->v.Call.args); + if (e->v.Call.keywords) { + VISIT_SEQ(c, keyword, e->v.Call.keywords); + n |= asdl_seq_LEN(e->v.Call.keywords) << 8; } - if (e->v.FormattedValue.format_spec) { - /* Evaluate the format spec, and update our opcode arg. */ - VISIT(c, expr, e->v.FormattedValue.format_spec); - oparg |= FVS_HAVE_SPEC; + if (e->v.Call.starargs) { + VISIT(c, expr, e->v.Call.starargs); + code |= 1; } - - /* And push our opcode and oparg */ - ADDOP_I(c, FORMAT_VALUE, oparg); - - return 1; -} - -static int -compiler_subkwargs(struct compiler *c, asdl_seq *keywords, Py_ssize_t begin, Py_ssize_t end) -{ - Py_ssize_t i, n = end - begin; - keyword_ty kw; - PyObject *keys, *key; - assert(n > 0); - if (n > 1) { - for (i = begin; i < end; i++) { - kw = asdl_seq_GET(keywords, i); - VISIT(c, expr, kw->value); - } - keys = PyTuple_New(n); - if (keys == NULL) { - return 0; - } - for (i = begin; i < end; i++) { - key = ((keyword_ty) asdl_seq_GET(keywords, i))->arg; - Py_INCREF(key); - PyTuple_SET_ITEM(keys, i - begin, key); - } - ADDOP_LOAD_CONST_NEW(c, keys); - ADDOP_I(c, BUILD_CONST_KEY_MAP, n); + if (e->v.Call.kwargs) { + VISIT(c, expr, e->v.Call.kwargs); + code |= 2; } - else { - /* a for loop only executes once */ - for (i = begin; i < end; i++) { - kw = asdl_seq_GET(keywords, i); - ADDOP_LOAD_CONST(c, kw->arg); - VISIT(c, expr, kw->value); - } - ADDOP_I(c, BUILD_MAP, n); + 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; } -/* 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) -{ - Py_ssize_t i, nseen, nelts, nkwelts; - int mustdictunpack = 0; - - /* the number of tuples and dictionaries on the stack */ - Py_ssize_t nsubargs = 0, nsubkwargs = 0; - - nelts = asdl_seq_LEN(args); - nkwelts = asdl_seq_LEN(keywords); - - for (i = 0; i < nkwelts; i++) { - keyword_ty kw = asdl_seq_GET(keywords, i); - if (kw->arg == NULL) { - mustdictunpack = 1; - break; - } - } - - nseen = n; /* the number of positional arguments on the stack */ - for (i = 0; i < nelts; i++) { - expr_ty elt = asdl_seq_GET(args, i); - if (elt->kind == Starred_kind) { - /* A star-arg. If we've seen positional arguments, - pack the positional arguments into a tuple. */ - if (nseen) { - ADDOP_I(c, BUILD_TUPLE, nseen); - nseen = 0; - nsubargs++; - } - VISIT(c, expr, elt->v.Starred.value); - nsubargs++; - } - else { - VISIT(c, expr, elt); - nseen++; - } - } - - /* Same dance again for keyword arguments */ - if (nsubargs || mustdictunpack) { - if (nseen) { - /* Pack up any trailing positional arguments. */ - ADDOP_I(c, BUILD_TUPLE, nseen); - nsubargs++; - } - if (nsubargs > 1) { - /* If we ended up with more than one stararg, we need - to concatenate them into a single sequence. */ - ADDOP_I(c, BUILD_TUPLE_UNPACK_WITH_CALL, nsubargs); - } - else if (nsubargs == 0) { - ADDOP_I(c, BUILD_TUPLE, 0); - } - nseen = 0; /* the number of keyword arguments on the stack following */ - for (i = 0; i < nkwelts; i++) { - keyword_ty kw = asdl_seq_GET(keywords, i); - if (kw->arg == NULL) { - /* A keyword argument unpacking. */ - if (nseen) { - if (!compiler_subkwargs(c, keywords, i - nseen, i)) - return 0; - nsubkwargs++; - nseen = 0; - } - VISIT(c, expr, kw->value); - nsubkwargs++; - } - else { - nseen++; - } - } - if (nseen) { - /* Pack up any trailing keyword arguments. */ - if (!compiler_subkwargs(c, keywords, nkwelts - nseen, nkwelts)) - return 0; - nsubkwargs++; - } - if (nsubkwargs > 1) { - /* Pack it all up */ - ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs); - } - ADDOP_I(c, CALL_FUNCTION_EX, nsubkwargs > 0); - return 1; - } - else if (nkwelts) { - PyObject *names; - VISIT_SEQ(c, keyword, keywords); - names = PyTuple_New(nkwelts); - if (names == NULL) { - return 0; - } - for (i = 0; i < nkwelts; i++) { - keyword_ty kw = asdl_seq_GET(keywords, i); - Py_INCREF(kw->arg); - PyTuple_SET_ITEM(names, i, kw->arg); - } - ADDOP_LOAD_CONST_NEW(c, names); - ADDOP_I(c, CALL_FUNCTION_KW, n + nelts + nkwelts); - return 1; - } - else { - ADDOP_I(c, CALL_FUNCTION, n + nelts); - return 1; - } -} - - -/* List and set comprehensions and generator expressions work by creating a - nested function to perform the actual iteration. This means that the - iteration variables don't leak into the current scope. - The defined function is called immediately following its definition, with the - result of that call being the result of the expression. - The LC/SC version returns the populated container, while the GE version is - flagged in symtable.c as a generator, so it returns the generator object - when the function is called. - - Possible cleanups: - - iterate over the generator sequence instead of using recursion -*/ - - -static int -compiler_comprehension_generator(struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type) -{ - comprehension_ty gen; - gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); - if (gen->is_async) { - return compiler_async_comprehension_generator( - c, generators, gen_index, elt, val, type); - } else { - return compiler_sync_comprehension_generator( - c, generators, gen_index, elt, val, type); - } -} - static int -compiler_sync_comprehension_generator(struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type) +compiler_listcomp_generator(struct compiler *c, asdl_seq *generators, + int gen_index, expr_ty elt) { /* generate code for the iterator, then each of the ifs, and then write to the element */ - comprehension_ty gen; + comprehension_ty l; basicblock *start, *anchor, *skip, *if_cleanup; - Py_ssize_t i, n; + int i, n; start = compiler_new_block(c); skip = compiler_new_block(c); @@ -4319,65 +2592,31 @@ compiler_sync_comprehension_generator(struct compiler *c, 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); - } + l = (comprehension_ty)asdl_seq_GET(generators, gen_index); + VISIT(c, expr, l->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); + VISIT(c, expr, l->target); /* XXX this needs to be cleaned up...a lot! */ - n = asdl_seq_LEN(gen->ifs); + n = asdl_seq_LEN(l->ifs); for (i = 0; i < n; i++) { - expr_ty e = (expr_ty)asdl_seq_GET(gen->ifs, i); - if (!compiler_jump_if(c, e, if_cleanup, 0)) - return 0; + expr_ty e = (expr_ty)asdl_seq_GET(l->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)) + if (!compiler_listcomp_generator(c, generators, gen_index, elt)) 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 '{k: v}', k is evaluated before v, so we do - the same. */ - VISIT(c, expr, elt); - VISIT(c, expr, val); - ADDOP_I(c, MAP_ADD, gen_index + 1); - break; - default: - return 0; - } + VISIT(c, expr, elt); + ADDOP_I(c, LIST_APPEND, gen_index+1); compiler_use_next_block(c, skip); } @@ -4389,20 +2628,49 @@ compiler_sync_comprehension_generator(struct compiler *c, } static int -compiler_async_comprehension_generator(struct compiler *c, - asdl_seq *generators, int gen_index, - expr_ty elt, expr_ty val, int type) +compiler_listcomp(struct compiler *c, expr_ty e) +{ + assert(e->kind == ListComp_kind); + ADDOP_I(c, BUILD_LIST, 0); + return compiler_listcomp_generator(c, e->v.ListComp.generators, 0, + e->v.ListComp.elt); +} + +/* Dict and set comprehensions and generator expressions work by creating a + nested function to perform the actual iteration. This means that the + iteration variables don't leak into the current scope. + The defined function is called immediately following its definition, with the + result of that call being the result of the expression. + The LC/SC version returns the populated container, while the GE version is + flagged in symtable.c as a generator, so it returns the generator object + when the function is called. + This code *knows* that the loop cannot contain break, continue, or return, + so it cheats and skips the SETUP_LOOP/POP_BLOCK steps used in normal loops. + + Possible cleanups: + - iterate over the generator sequence instead of using recursion +*/ + +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, *if_cleanup, *except; - Py_ssize_t i, n; + basicblock *start, *anchor, *skip, *if_cleanup; + int i, n; + start = compiler_new_block(c); - except = compiler_new_block(c); + skip = compiler_new_block(c); if_cleanup = compiler_new_block(c); + anchor = compiler_new_block(c); - if (start == NULL || if_cleanup == NULL || except == NULL) { + if (start == NULL || skip == NULL || if_cleanup == NULL || + anchor == NULL) return 0; - } gen = (comprehension_ty)asdl_seq_GET(generators, gen_index); @@ -4414,23 +2682,19 @@ compiler_async_comprehension_generator(struct compiler *c, else { /* Sub-iter - calculate on the fly */ VISIT(c, expr, gen->iter); - ADDOP(c, GET_AITER); + ADDOP(c, GET_ITER); } - compiler_use_next_block(c, start); - - ADDOP_JREL(c, SETUP_FINALLY, except); - ADDOP(c, GET_ANEXT); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - ADDOP(c, POP_BLOCK); + 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); - if (!compiler_jump_if(c, e, if_cleanup, 0)) - return 0; + VISIT(c, expr, e); + ADDOP_JABS(c, POP_JUMP_IF_FALSE, if_cleanup); NEXT_BLOCK(c); } @@ -4449,67 +2713,46 @@ compiler_async_comprehension_generator(struct compiler *c, 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 '{k: v}', k is evaluated before v, so we do + /* With 'd[k] = v', v is evaluated before k, so we do the same. */ - VISIT(c, expr, elt); 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, except); - ADDOP(c, END_ASYNC_FOR); + 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) +compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name, + asdl_seq *generators, expr_ty elt, expr_ty val) { PyCodeObject *co = NULL; - comprehension_ty outermost; - PyObject *qualname = NULL; - int is_async_function = c->u->u_ste->ste_coroutine; - int is_async_generator = 0; + expr_ty outermost_iter; - outermost = (comprehension_ty) asdl_seq_GET(generators, 0); + outermost_iter = ((comprehension_ty) + asdl_seq_GET(generators, 0))->iter; - if (!compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION, - (void *)e, e->lineno)) - { + if (!compiler_enter_scope(c, name, (void *)e, e->lineno)) goto error; - } - - is_async_generator = c->u->u_ste->ste_coroutine; - - if (is_async_generator && !is_async_function && type != COMP_GENEXP) { - compiler_error(c, "asynchronous comprehension outside of " - "an asynchronous function"); - goto error_in_scope; - } if (type != COMP_GENEXP) { int op; switch (type) { - case COMP_LISTCOMP: - op = BUILD_LIST; - break; case COMP_SETCOMP: op = BUILD_SET; break; @@ -4534,38 +2777,21 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type, } co = assemble(c, 1); - qualname = c->u->u_qualname; - Py_INCREF(qualname); compiler_exit_scope(c); if (co == NULL) goto error; - if (!compiler_make_closure(c, co, 0, qualname)) + if (!compiler_make_closure(c, co, 0)) goto error; - Py_DECREF(qualname); Py_DECREF(co); - VISIT(c, expr, outermost->iter); - - if (outermost->is_async) { - ADDOP(c, GET_AITER); - } else { - ADDOP(c, GET_ITER); - } - + VISIT(c, expr, outermost_iter); + ADDOP(c, GET_ITER); ADDOP_I(c, CALL_FUNCTION, 1); - - if (is_async_generator && type != COMP_GENEXP) { - ADDOP(c, GET_AWAITABLE); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - } - return 1; error_in_scope: compiler_exit_scope(c); error: - Py_XDECREF(qualname); Py_XDECREF(co); return 0; } @@ -4575,7 +2801,7 @@ compiler_genexp(struct compiler *c, expr_ty e) { static identifier name; if (!name) { - name = PyUnicode_InternFromString("<genexpr>"); + name = PyString_FromString("<genexpr>"); if (!name) return 0; } @@ -4586,26 +2812,11 @@ compiler_genexp(struct compiler *c, expr_ty e) } static int -compiler_listcomp(struct compiler *c, expr_ty e) -{ - static identifier name; - if (!name) { - name = PyUnicode_InternFromString("<listcomp>"); - 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_InternFromString("<setcomp>"); + name = PyString_FromString("<setcomp>"); if (!name) return 0; } @@ -4615,13 +2826,12 @@ compiler_setcomp(struct compiler *c, expr_ty e) e->v.SetComp.elt, NULL); } - static int compiler_dictcomp(struct compiler *c, expr_ty e) { static identifier name; if (!name) { - name = PyUnicode_InternFromString("<dictcomp>"); + name = PyString_FromString("<dictcomp>"); if (!name) return 0; } @@ -4631,10 +2841,10 @@ compiler_dictcomp(struct compiler *c, expr_ty e) 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; } @@ -4648,42 +2858,36 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(expr_ty e) { - if (e->kind == Constant_kind) { - return PyObject_IsTrue(e->v.Constant.value); + switch (e->kind) { + case Num_kind: + return PyObject_IsTrue(e->v.Num.n); + case Str_kind: + return PyObject_IsTrue(e->v.Str.s); + case Name_kind: + /* __debug__ is not assignable, so we can optimize + * it away in if and while statements */ + if (strcmp(PyString_AS_STRING(e->v.Name.id), + "__debug__") == 0) + return ! Py_OptimizeFlag; + /* fall through */ + default: + return -1; } - return -1; -} - -static int -compiler_with_except_finish(struct compiler *c) { - basicblock *exit; - exit = compiler_new_block(c); - if (exit == NULL) - return 0; - ADDOP_JABS(c, POP_JUMP_IF_TRUE, exit); - ADDOP(c, RERAISE); - compiler_use_next_block(c, exit); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_EXCEPT); - ADDOP(c, POP_TOP); - return 1; } /* - Implements the async with statement. + Implements the with statement from PEP 343. The semantics outlined in that PEP are as follows: - async with EXPR as VAR: + with EXPR as VAR: BLOCK It is implemented roughly as: context = EXPR - exit = context.__aexit__ # not calling it - value = await context.__aenter__() + exit = context.__exit__ # not calling it + value = context.__enter__() try: VAR = value # if VAR present in the syntax BLOCK @@ -4692,183 +2896,77 @@ compiler_with_except_finish(struct compiler *c) { exc = copy of (exception, instance, traceback) else: exc = (None, None, None) - if not (await exit(*exc)): - raise - */ -static int -compiler_async_with(struct compiler *c, stmt_ty s, int pos) -{ - basicblock *block, *final, *exit; - withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos); - - assert(s->kind == AsyncWith_kind); - if (c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT){ - c->u->u_ste->ste_coroutine = 1; - } else if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION){ - return compiler_error(c, "'async with' outside async function"); - } - - block = compiler_new_block(c); - final = compiler_new_block(c); - exit = compiler_new_block(c); - if (!block || !final || !exit) - return 0; - - /* Evaluate EXPR */ - VISIT(c, expr, item->context_expr); - - ADDOP(c, BEFORE_ASYNC_WITH); - ADDOP(c, GET_AWAITABLE); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - - ADDOP_JREL(c, SETUP_ASYNC_WITH, final); - - /* SETUP_ASYNC_WITH pushes a finally block. */ - compiler_use_next_block(c, block); - if (!compiler_push_fblock(c, ASYNC_WITH, block, final, NULL)) { - return 0; - } - - if (item->optional_vars) { - VISIT(c, expr, item->optional_vars); - } - else { - /* Discard result from context.__aenter__() */ - ADDOP(c, POP_TOP); - } - - pos++; - if (pos == asdl_seq_LEN(s->v.AsyncWith.items)) - /* BLOCK code */ - VISIT_SEQ(c, stmt, s->v.AsyncWith.body) - else if (!compiler_async_with(c, s, pos)) - return 0; - - compiler_pop_fblock(c, ASYNC_WITH, block); - ADDOP(c, POP_BLOCK); - /* End of body; start the cleanup */ - - /* For successful outcome: - * call __exit__(None, None, None) - */ - if(!compiler_call_exit_with_nones(c)) - return 0; - ADDOP(c, GET_AWAITABLE); - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, YIELD_FROM); - - ADDOP(c, POP_TOP); - - ADDOP_JABS(c, JUMP_ABSOLUTE, exit); - - /* For exceptional outcome: */ - compiler_use_next_block(c, final); - - ADDOP(c, WITH_EXCEPT_START); - ADDOP(c, GET_AWAITABLE); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - compiler_with_except_finish(c); - -compiler_use_next_block(c, exit); - return 1; -} - - -/* - Implements the with statement from PEP 343. - with EXPR as VAR: - BLOCK - is implemented as: - <code for EXPR> - SETUP_WITH E - <code to store to VAR> or POP_TOP - <code for BLOCK> - LOAD_CONST (None, None, None) - CALL_FUNCTION_EX 0 - JUMP_FORWARD EXIT - E: WITH_EXCEPT_START (calls EXPR.__exit__) - POP_JUMP_IF_TRUE T: - RERAISE - T: POP_TOP * 3 (remove exception from stack) - POP_EXCEPT - POP_TOP - EXIT: + exit(*exc) */ - static int -compiler_with(struct compiler *c, stmt_ty s, int pos) +compiler_with(struct compiler *c, stmt_ty s) { - basicblock *block, *final, *exit; - withitem_ty item = asdl_seq_GET(s->v.With.items, pos); + basicblock *block, *finally; assert(s->kind == With_kind); block = compiler_new_block(c); - final = compiler_new_block(c); - exit = compiler_new_block(c); - if (!block || !final || !exit) + finally = compiler_new_block(c); + if (!block || !finally) return 0; /* Evaluate EXPR */ - VISIT(c, expr, item->context_expr); - /* Will push bound __exit__ */ - ADDOP_JREL(c, SETUP_WITH, final); + VISIT(c, expr, s->v.With.context_expr); + ADDOP_JREL(c, SETUP_WITH, finally); /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); - if (!compiler_push_fblock(c, WITH, block, final, NULL)) { + /* Note that the block is actually called SETUP_WITH in ceval.c, but + functions the same as SETUP_FINALLY except that exceptions are + normalized. */ + if (!compiler_push_fblock(c, FINALLY_TRY, block)) { return 0; } - if (item->optional_vars) { - VISIT(c, expr, item->optional_vars); + if (s->v.With.optional_vars) { + VISIT(c, expr, s->v.With.optional_vars); } else { /* Discard result from context.__enter__() */ ADDOP(c, POP_TOP); } - pos++; - if (pos == asdl_seq_LEN(s->v.With.items)) - /* BLOCK code */ - VISIT_SEQ(c, stmt, s->v.With.body) - else if (!compiler_with(c, s, pos)) - return 0; + /* BLOCK code */ + VISIT_SEQ(c, stmt, s->v.With.body); + /* End of try block; start the finally block */ ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, WITH, block); - - /* End of body; start the cleanup. */ - - /* For successful outcome: - * call __exit__(None, None, None) - */ - if (!compiler_call_exit_with_nones(c)) - return 0; - ADDOP(c, POP_TOP); - ADDOP_JREL(c, JUMP_FORWARD, exit); + compiler_pop_fblock(c, FINALLY_TRY, block); - /* For exceptional outcome: */ - compiler_use_next_block(c, final); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + compiler_use_next_block(c, finally); + if (!compiler_push_fblock(c, FINALLY_END, finally)) + return 0; - ADDOP(c, WITH_EXCEPT_START); - compiler_with_except_finish(c); + /* Finally block starts; context.__exit__ is on the stack under + the exception or return information. Just issue our magic + opcode. */ + ADDOP(c, WITH_CLEANUP); - compiler_use_next_block(c, exit); + /* Finally block ends. */ + ADDOP(c, END_FINALLY); + compiler_pop_fblock(c, FINALLY_END, finally); return 1; } static int -compiler_visit_expr1(struct compiler *c, expr_ty e) +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 = false; + } switch (e->kind) { - case NamedExpr_kind: - VISIT(c, expr, e->v.NamedExpr.value); - ADDOP(c, DUP_TOP); - VISIT(c, expr, e->v.NamedExpr.target); - break; case BoolOp_kind: return compiler_boolop(c, e); case BinOp_kind: @@ -4885,17 +2983,29 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) case IfExp_kind: return compiler_ifexp(c, e); case Dict_kind: - return compiler_dict(c, e); + 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: - return compiler_set(c, e); - case GeneratorExp_kind: - return compiler_genexp(c, e); + n = asdl_seq_LEN(e->v.Set.elts); + VISIT_SEQ(c, expr, e->v.Set.elts); + ADDOP_I(c, BUILD_SET, n); + break; 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 GeneratorExp_kind: + return compiler_genexp(c, e); case Yield_kind: if (c->u->u_ste->ste_type != FunctionBlock) return compiler_error(c, "'yield' outside function"); @@ -4903,50 +3013,24 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) VISIT(c, expr, e->v.Yield.value); } else { - ADDOP_LOAD_CONST(c, Py_None); + ADDOP_O(c, LOAD_CONST, Py_None, consts); } ADDOP(c, YIELD_VALUE); break; - case YieldFrom_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'yield' outside function"); - - if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION) - return compiler_error(c, "'yield from' inside async function"); - - VISIT(c, expr, e->v.YieldFrom.value); - ADDOP(c, GET_YIELD_FROM_ITER); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - break; - case Await_kind: - if (!(c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT)){ - if (c->u->u_ste->ste_type != FunctionBlock){ - return compiler_error(c, "'await' outside function"); - } - - if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION && - c->u->u_scope_type != COMPILER_SCOPE_COMPREHENSION){ - return compiler_error(c, "'await' outside async function"); - } - } - - VISIT(c, expr, e->v.Await.value); - ADDOP(c, GET_AWAITABLE); - ADDOP_LOAD_CONST(c, Py_None); - ADDOP(c, YIELD_FROM); - break; case Compare_kind: return compiler_compare(c, e); case Call_kind: return compiler_call(c, e); - case Constant_kind: - ADDOP_LOAD_CONST(c, e->v.Constant.value); + case Repr_kind: + VISIT(c, expr, e->v.Repr.value); + ADDOP(c, UNARY_CONVERT); + break; + case Num_kind: + ADDOP_O(c, LOAD_CONST, e->v.Num.n, consts); + break; + case Str_kind: + ADDOP_O(c, LOAD_CONST, e->v.Str.s, consts); break; - case JoinedStr_kind: - return compiler_joined_str(c, e); - case FormattedValue_kind: - return compiler_formatted_value(c, e); /* The following exprs can be assignment targets. */ case Attribute_kind: if (e->v.Attribute.ctx != AugStore) @@ -4954,13 +3038,13 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) switch (e->v.Attribute.ctx) { case AugLoad: ADDOP(c, DUP_TOP); - /* Fall through */ + /* 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 */ + /* Fall through to save */ case Store: ADDOP_NAME(c, STORE_ATTR, e->v.Attribute.attr, names); break; @@ -4981,12 +3065,6 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) VISIT_SLICE(c, e->v.Subscript.slice, AugLoad); break; case Load: - if (!check_subscripter(c, e->v.Subscript.value)) { - return 0; - } - if (!check_index(c, e->v.Subscript.value, e->v.Subscript.slice)) { - return 0; - } VISIT(c, expr, e->v.Subscript.value); VISIT_SLICE(c, e->v.Subscript.slice, Load); break; @@ -5008,17 +3086,6 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) 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't use starred expression here"); - } 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 */ @@ -5031,31 +3098,6 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) } static int -compiler_visit_expr(struct compiler *c, expr_ty e) -{ - /* If expr e has a different line number than the last expr/stmt, - set a new line number for the next instruction. - */ - int old_lineno = c->u->u_lineno; - int old_col_offset = c->u->u_col_offset; - if (e->lineno != c->u->u_lineno) { - 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; - - int res = compiler_visit_expr1(c, e); - - if (old_lineno != c->u->u_lineno) { - c->u->u_lineno = old_lineno; - c->u->u_lineno_set = 0; - } - c->u->u_col_offset = old_col_offset; - return res; -} - -static int compiler_augassign(struct compiler *c, stmt_ty s) { expr_ty e = s->v.AugAssign.target; @@ -5066,8 +3108,7 @@ compiler_augassign(struct compiler *c, stmt_ty s) switch (e->kind) { case Attribute_kind: auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr, - AugLoad, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset, c->c_arena); + AugLoad, e->lineno, e->col_offset, c->c_arena); if (auge == NULL) return 0; VISIT(c, expr, auge); @@ -5078,8 +3119,7 @@ compiler_augassign(struct compiler *c, stmt_ty s) break; case Subscript_kind: auge = Subscript(e->v.Subscript.value, e->v.Subscript.slice, - AugLoad, e->lineno, e->col_offset, - e->end_lineno, e->end_col_offset, c->c_arena); + AugLoad, e->lineno, e->col_offset, c->c_arena); if (auge == NULL) return 0; VISIT(c, expr, auge); @@ -5104,146 +3144,40 @@ compiler_augassign(struct compiler *c, stmt_ty s) } static int -check_ann_expr(struct compiler *c, expr_ty e) -{ - VISIT(c, expr, e); - ADDOP(c, POP_TOP); - return 1; -} - -static int -check_annotation(struct compiler *c, stmt_ty s) -{ - /* Annotations are only evaluated in a module or class. */ - if (c->u->u_scope_type == COMPILER_SCOPE_MODULE || - c->u->u_scope_type == COMPILER_SCOPE_CLASS) { - return check_ann_expr(c, s->v.AnnAssign.annotation); - } - return 1; -} - -static int -check_ann_slice(struct compiler *c, slice_ty sl) +compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b) { - switch(sl->kind) { - case Index_kind: - return check_ann_expr(c, sl->v.Index.value); - case Slice_kind: - if (sl->v.Slice.lower && !check_ann_expr(c, sl->v.Slice.lower)) { - return 0; - } - if (sl->v.Slice.upper && !check_ann_expr(c, sl->v.Slice.upper)) { - return 0; - } - if (sl->v.Slice.step && !check_ann_expr(c, sl->v.Slice.step)) { - return 0; - } - break; - default: - PyErr_SetString(PyExc_SystemError, - "unexpected slice kind"); + struct fblockinfo *f; + if (c->u->u_nfblocks >= CO_MAXBLOCKS) { + PyErr_SetString(PyExc_SyntaxError, + "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 int -check_ann_subscr(struct compiler *c, slice_ty sl) +static void +compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) { - /* We check that everything in a subscript is defined at runtime. */ - Py_ssize_t i, n; - - switch (sl->kind) { - case Index_kind: - case Slice_kind: - if (!check_ann_slice(c, sl)) { - return 0; - } - break; - case ExtSlice_kind: - n = asdl_seq_LEN(sl->v.ExtSlice.dims); - for (i = 0; i < n; i++) { - slice_ty subsl = (slice_ty)asdl_seq_GET(sl->v.ExtSlice.dims, i); - switch (subsl->kind) { - case Index_kind: - case Slice_kind: - if (!check_ann_slice(c, subsl)) { - return 0; - } - break; - case ExtSlice_kind: - default: - PyErr_SetString(PyExc_SystemError, - "extended slice invalid in nested slice"); - return 0; - } - } - break; - default: - PyErr_Format(PyExc_SystemError, - "invalid subscript kind %d", sl->kind); - return 0; - } - return 1; + 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_annassign(struct compiler *c, stmt_ty s) -{ - expr_ty targ = s->v.AnnAssign.target; - PyObject* mangled; - - assert(s->kind == AnnAssign_kind); - - /* We perform the actual assignment first. */ - if (s->v.AnnAssign.value) { - VISIT(c, expr, s->v.AnnAssign.value); - VISIT(c, expr, targ); - } - switch (targ->kind) { - case Name_kind: - /* If we have a simple name in a module or class, store annotation. */ - if (s->v.AnnAssign.simple && - (c->u->u_scope_type == COMPILER_SCOPE_MODULE || - c->u->u_scope_type == COMPILER_SCOPE_CLASS)) { - if (c->c_future->ff_features & CO_FUTURE_ANNOTATIONS) { - VISIT(c, annexpr, s->v.AnnAssign.annotation) - } - else { - VISIT(c, expr, s->v.AnnAssign.annotation); - } - ADDOP_NAME(c, LOAD_NAME, __annotations__, names); - mangled = _Py_Mangle(c->u->u_private, targ->v.Name.id); - ADDOP_LOAD_CONST_NEW(c, mangled); - ADDOP(c, STORE_SUBSCR); - } - break; - case Attribute_kind: - if (!s->v.AnnAssign.value && - !check_ann_expr(c, targ->v.Attribute.value)) { - return 0; - } - break; - case Subscript_kind: - if (!s->v.AnnAssign.value && - (!check_ann_expr(c, targ->v.Subscript.value) || - !check_ann_subscr(c, targ->v.Subscript.slice))) { - return 0; - } - break; - default: - PyErr_Format(PyExc_SystemError, - "invalid node type (%d) for annotated assignment", - targ->kind); - return 0; - } - /* Annotation is evaluated last. */ - if (!s->v.AnnAssign.simple && !check_annotation(c, s)) { - return 0; +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 1; + return 0; } - /* Raises a SyntaxError and returns 0. If something goes wrong, a different exception may be raised. */ @@ -5254,13 +3188,13 @@ compiler_error(struct compiler *c, const char *errstr) PyObject *loc; PyObject *u = NULL, *v = NULL; - loc = PyErr_ProgramTextObject(c->c_filename, c->u->u_lineno); + loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(OiiO)", c->c_filename, c->u->u_lineno, - c->u->u_col_offset + 1, loc); + u = Py_BuildValue("(ziOO)", c->c_filename, c->u->u_lineno, + Py_None, loc); if (!u) goto exit; v = Py_BuildValue("(zO)", errstr, u); @@ -5274,41 +3208,6 @@ compiler_error(struct compiler *c, const char *errstr) return 0; } -/* Emits a SyntaxWarning and returns 1 on success. - If a SyntaxWarning raised as error, replaces it with a SyntaxError - and returns 0. -*/ -static int -compiler_warn(struct compiler *c, const char *format, ...) -{ - va_list vargs; -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - PyObject *msg = PyUnicode_FromFormatV(format, vargs); - va_end(vargs); - if (msg == NULL) { - return 0; - } - if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, c->c_filename, - c->u->u_lineno, NULL, NULL) < 0) - { - if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { - /* Replace the SyntaxWarning exception with a SyntaxError - to get a more accurate error report */ - PyErr_Clear(); - assert(PyUnicode_AsUTF8(msg) != NULL); - compiler_error(c, PyUnicode_AsUTF8(msg)); - } - Py_DECREF(msg); - return 0; - } - Py_DECREF(msg); - return 1; -} - static int compiler_handle_subscr(struct compiler *c, const char *kind, expr_context_ty ctx) @@ -5329,7 +3228,7 @@ compiler_handle_subscr(struct compiler *c, const char *kind, return 0; } if (ctx == AugLoad) { - ADDOP(c, DUP_TOP_TWO); + ADDOP_I(c, DUP_TOPX, 2); } else if (ctx == AugStore) { ADDOP(c, ROT_THREE); @@ -5349,14 +3248,14 @@ compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) VISIT(c, expr, s->v.Slice.lower); } else { - ADDOP_LOAD_CONST(c, Py_None); + ADDOP_O(c, LOAD_CONST, Py_None, consts); } if (s->v.Slice.upper) { VISIT(c, expr, s->v.Slice.upper); } else { - ADDOP_LOAD_CONST(c, Py_None); + ADDOP_O(c, LOAD_CONST, Py_None, consts); } if (s->v.Slice.step) { @@ -5368,10 +3267,64 @@ compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) } static int +compiler_simple_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) +{ + int op = 0, slice_offset = 0, stack_count = 0; + + assert(s->v.Slice.step == NULL); + if (s->v.Slice.lower) { + slice_offset++; + stack_count++; + if (ctx != AugStore) + VISIT(c, expr, s->v.Slice.lower); + } + if (s->v.Slice.upper) { + slice_offset += 2; + stack_count++; + if (ctx != AugStore) + VISIT(c, expr, s->v.Slice.upper); + } + + if (ctx == AugLoad) { + switch (stack_count) { + case 0: ADDOP(c, DUP_TOP); break; + case 1: ADDOP_I(c, DUP_TOPX, 2); break; + case 2: ADDOP_I(c, DUP_TOPX, 3); break; + } + } + else if (ctx == AugStore) { + switch (stack_count) { + case 0: ADDOP(c, ROT_TWO); break; + case 1: ADDOP(c, ROT_THREE); break; + case 2: ADDOP(c, ROT_FOUR); break; + } + } + + switch (ctx) { + case AugLoad: /* fall through to Load */ + case Load: op = SLICE; break; + case AugStore:/* fall through to Store */ + case Store: op = STORE_SLICE; break; + case Del: op = DELETE_SLICE; break; + case Param: + default: + PyErr_SetString(PyExc_SystemError, + "param invalid in simple slice"); + return 0; + } + + ADDOP(c, op + slice_offset); + return 1; +} + +static int compiler_visit_nested_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) { switch (s->kind) { + case Ellipsis_kind: + ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); + break; case Slice_kind: return compiler_slice(c, s, ctx); case Index_kind: @@ -5389,7 +3342,7 @@ compiler_visit_nested_slice(struct compiler *c, slice_ty s, static int compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) { - const char * kindname = NULL; + char * kindname = NULL; switch (s->kind) { case Index_kind: kindname = "index"; @@ -5397,8 +3350,16 @@ compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) VISIT(c, expr, s->v.Index.value); } break; + case Ellipsis_kind: + kindname = "ellipsis"; + if (ctx != AugStore) { + ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); + } + break; case Slice_kind: kindname = "slice"; + if (!s->v.Slice.step) + return compiler_simple_slice(c, s, ctx); if (ctx != AugStore) { if (!compiler_slice(c, s, ctx)) return 0; @@ -5407,7 +3368,7 @@ compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) case ExtSlice_kind: kindname = "extended slice"; if (ctx != AugStore) { - Py_ssize_t i, n = asdl_seq_LEN(s->v.ExtSlice.dims); + 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); @@ -5425,6 +3386,7 @@ compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx) return compiler_handle_subscr(c, kindname, ctx); } + /* End of the compiler section, beginning of the assembler section */ /* do depth-first search of basic block graph, starting with block. @@ -5445,40 +3407,66 @@ struct assembler { }; static void -dfs(struct compiler *c, basicblock *b, struct assembler *a, int end) +dfs(struct compiler *c, basicblock *b, struct assembler *a) { - int i, j; - - /* Get rid of recursion for normal control flow. - Since the number of blocks is limited, unused space in a_postorder - (from a_nblocks to end) can be used as a stack for still not ordered - blocks. */ - for (j = end; b && !b->b_seen; b = b->b_next) { - b->b_seen = 1; - assert(a->a_nblocks < j); - a->a_postorder[--j] = b; - } - while (j < end) { - b = a->a_postorder[j++]; - for (i = 0; i < b->b_iused; i++) { - struct instr *instr = &b->b_instr[i]; - if (instr->i_jrel || instr->i_jabs) - dfs(c, instr->i_target, a, j); - } - assert(a->a_nblocks < j); - a->a_postorder[a->a_nblocks++] = b; - } -} + int i; + struct instr *instr = NULL; -Py_LOCAL_INLINE(void) -stackdepth_push(basicblock ***sp, basicblock *b, int depth) -{ - assert(b->b_startdepth < 0 || b->b_startdepth == depth); - if (b->b_startdepth < depth && b->b_startdepth < 100) { - assert(b->b_startdepth < 0); - b->b_startdepth = depth; - *(*sp)++ = b; + 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; + } + else if (instr->i_opcode == JUMP_IF_TRUE_OR_POP || + instr->i_opcode == JUMP_IF_FALSE_OR_POP) + depth = depth - 1; + 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; } /* Find the flow path that needs the largest stack. We assume that @@ -5487,69 +3475,16 @@ stackdepth_push(basicblock ***sp, basicblock *b, int depth) static int stackdepth(struct compiler *c) { - basicblock *b, *entryblock = NULL; - basicblock **stack, **sp; - int nblocks = 0, maxdepth = 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; - nblocks++; } if (!entryblock) return 0; - stack = (basicblock **)PyObject_Malloc(sizeof(basicblock *) * nblocks); - if (!stack) { - PyErr_NoMemory(); - return -1; - } - - sp = stack; - stackdepth_push(&sp, entryblock, 0); - while (sp != stack) { - b = *--sp; - int depth = b->b_startdepth; - assert(depth >= 0); - basicblock *next = b->b_next; - for (int i = 0; i < b->b_iused; i++) { - struct instr *instr = &b->b_instr[i]; - int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0); - if (effect == PY_INVALID_STACK_EFFECT) { - fprintf(stderr, "opcode = %d\n", instr->i_opcode); - Py_FatalError("PyCompile_OpcodeStackEffect()"); - } - int new_depth = depth + effect; - if (new_depth > maxdepth) { - maxdepth = new_depth; - } - assert(depth >= 0); /* invalid code or bug in stackdepth() */ - if (instr->i_jrel || instr->i_jabs) { - effect = stack_effect(instr->i_opcode, instr->i_oparg, 1); - assert(effect != PY_INVALID_STACK_EFFECT); - int target_depth = depth + effect; - if (target_depth > maxdepth) { - maxdepth = target_depth; - } - assert(target_depth >= 0); /* invalid code or bug in stackdepth() */ - stackdepth_push(&sp, instr->i_target, target_depth); - } - depth = new_depth; - if (instr->i_opcode == JUMP_ABSOLUTE || - instr->i_opcode == JUMP_FORWARD || - instr->i_opcode == RETURN_VALUE || - instr->i_opcode == RAISE_VARARGS || - instr->i_opcode == RERAISE) - { - /* remaining code is dead */ - next = NULL; - break; - } - } - if (next != NULL) { - stackdepth_push(&sp, next, depth); - } - } - PyObject_Free(stack); - return maxdepth; + return stackdepth_walk(c, entryblock, 0, 0); } static int @@ -5557,13 +3492,13 @@ 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); + a->a_bytecode = PyString_FromStringAndSize(NULL, DEFAULT_CODE_SIZE); if (!a->a_bytecode) return 0; - a->a_lnotab = PyBytes_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); + a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE); if (!a->a_lnotab) return 0; - if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) { + if (nblocks > PY_SIZE_MAX / sizeof(basicblock *)) { PyErr_NoMemory(); return 0; } @@ -5585,6 +3520,18 @@ assemble_free(struct assembler *a) PyObject_Free(a->a_postorder); } +/* Return the size of a basic block in bytes. */ + +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) */ +} + static int blocksize(basicblock *b) { @@ -5592,7 +3539,7 @@ blocksize(basicblock *b) int size = 0; for (i = 0; i < b->b_iused; i++) - size += instrsize(b->b_instr[i].i_oparg); + size += instrsize(&b->b_instr[i]); return size; } @@ -5604,13 +3551,14 @@ static int assemble_lnotab(struct assembler *a, struct instr *i) { int d_bytecode, d_lineno; - Py_ssize_t len; + int len; unsigned char *lnotab; - d_bytecode = (a->a_offset - a->a_lineno_off) * sizeof(_Py_CODEUNIT); + 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; @@ -5618,7 +3566,7 @@ assemble_lnotab(struct assembler *a, struct instr *i) 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); + len = PyString_GET_SIZE(a->a_lnotab); if (nbytes >= len) { if ((len <= INT_MAX / 2) && (len * 2 < nbytes)) len = nbytes; @@ -5628,11 +3576,11 @@ assemble_lnotab(struct assembler *a, struct instr *i) PyErr_NoMemory(); return 0; } - if (_PyBytes_Resize(&a->a_lnotab, len) < 0) + if (_PyString_Resize(&a->a_lnotab, len) < 0) return 0; } lnotab = (unsigned char *) - PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; for (j = 0; j < ncodes; j++) { *lnotab++ = 255; *lnotab++ = 0; @@ -5640,23 +3588,11 @@ assemble_lnotab(struct assembler *a, struct instr *i) d_bytecode -= ncodes * 255; a->a_lnotab_off += ncodes * 2; } - assert(0 <= d_bytecode && d_bytecode <= 255); - - if (d_lineno < -128 || 127 < d_lineno) { - int j, nbytes, ncodes, k; - if (d_lineno < 0) { - k = -128; - /* use division on positive numbers */ - ncodes = (-d_lineno) / 128; - } - else { - k = 127; - ncodes = d_lineno / 127; - } - d_lineno -= ncodes * k; - assert(ncodes >= 1); + 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); + len = PyString_GET_SIZE(a->a_lnotab); if (nbytes >= len) { if ((len <= INT_MAX / 2) && len * 2 < nbytes) len = nbytes; @@ -5666,29 +3602,29 @@ assemble_lnotab(struct assembler *a, struct instr *i) PyErr_NoMemory(); return 0; } - if (_PyBytes_Resize(&a->a_lnotab, len) < 0) + if (_PyString_Resize(&a->a_lnotab, len) < 0) return 0; } lnotab = (unsigned char *) - PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; *lnotab++ = d_bytecode; - *lnotab++ = k; + *lnotab++ = 255; d_bytecode = 0; for (j = 1; j < ncodes; j++) { *lnotab++ = 0; - *lnotab++ = k; + *lnotab++ = 255; } + d_lineno -= ncodes * 255; a->a_lnotab_off += ncodes * 2; } - assert(-128 <= d_lineno && d_lineno <= 127); - len = PyBytes_GET_SIZE(a->a_lnotab); + len = PyString_GET_SIZE(a->a_lnotab); if (a->a_lnotab_off + 2 >= len) { - if (_PyBytes_Resize(&a->a_lnotab, len * 2) < 0) + if (_PyString_Resize(&a->a_lnotab, len * 2) < 0) return 0; } lnotab = (unsigned char *) - PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off; + PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; a->a_lnotab_off += 2; if (d_bytecode) { @@ -5712,23 +3648,38 @@ assemble_lnotab(struct assembler *a, struct instr *i) static int assemble_emit(struct assembler *a, struct instr *i) { - int size, arg = 0; - Py_ssize_t len = PyBytes_GET_SIZE(a->a_bytecode); - _Py_CODEUNIT *code; + int size, arg = 0, ext = 0; + Py_ssize_t len = PyString_GET_SIZE(a->a_bytecode); + char *code; - arg = i->i_oparg; - size = instrsize(arg); + 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 / (int)sizeof(_Py_CODEUNIT)) { + if (a->a_offset + size >= len) { if (len > PY_SSIZE_T_MAX / 2) return 0; - if (_PyBytes_Resize(&a->a_bytecode, len * 2) < 0) + if (_PyString_Resize(&a->a_bytecode, len * 2) < 0) return 0; } - code = (_Py_CODEUNIT *)PyBytes_AS_STRING(a->a_bytecode) + a->a_offset; + code = PyString_AS_STRING(a->a_bytecode) + a->a_offset; a->a_offset += size; - write_op_arg(code, i->i_opcode, arg, 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; } @@ -5736,7 +3687,7 @@ static void assemble_jump_offsets(struct assembler *a, struct compiler *c) { basicblock *b; - int bsize, totsize, extended_arg_recompile; + int bsize, totsize, extended_arg_count = 0, last_extended_arg_count; int i; /* Compute the size of each block and fixup jump args. @@ -5749,27 +3700,27 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) b->b_offset = totsize; totsize += bsize; } - extended_arg_recompile = 0; + 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]; - int isize = instrsize(instr->i_oparg); /* Relative jumps are computed relative to the instruction pointer after fetching the jump instruction. */ - bsize += isize; - if (instr->i_jabs || instr->i_jrel) { + bsize += instrsize(instr); + if (instr->i_jabs) instr->i_oparg = instr->i_target->b_offset; - if (instr->i_jrel) { - instr->i_oparg -= bsize; - } - instr->i_oparg *= sizeof(_Py_CODEUNIT); - if (instrsize(instr->i_oparg) != isize) { - extended_arg_recompile = 1; - } + 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++; } } @@ -5779,7 +3730,7 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) 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 + 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. @@ -5787,20 +3738,23 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c) ones in jump instructions. So this should converge fairly quickly. */ - } while (extended_arg_recompile); + } while (last_extended_arg_count != extended_arg_count); } static PyObject * -dict_keys_inorder(PyObject *dict, Py_ssize_t offset) +dict_keys_inorder(PyObject *dict, int offset) { PyObject *tuple, *k, *v; - Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict); + 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); + i = PyInt_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, 1); Py_INCREF(k); assert((i - offset) < size); assert((i - offset) >= 0); @@ -5809,46 +3763,20 @@ dict_keys_inorder(PyObject *dict, Py_ssize_t offset) return tuple; } -static PyObject * -consts_dict_keys_inorder(PyObject *dict) -{ - PyObject *consts, *k, *v; - Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict); - - consts = PyList_New(size); /* PyCode_Optimize() requires a list */ - if (consts == NULL) - return NULL; - while (PyDict_Next(dict, &pos, &k, &v)) { - i = PyLong_AS_LONG(v); - /* The keys of the dictionary can be tuples wrapping a contant. - * (see compiler_add_o and _PyCode_ConstantKey). In that case - * the object we want is always second. */ - if (PyTuple_CheckExact(k)) { - k = PyTuple_GET_ITEM(k, 1); - } - Py_INCREF(k); - assert(i < size); - assert(i >= 0); - PyList_SET_ITEM(consts, i, k); - } - return consts; -} - static int compute_code_flags(struct compiler *c) { PySTEntryObject *ste = c->u->u_ste; - int flags = 0; + int flags = 0, n; + if (ste->ste_type != ModuleBlock) + flags |= CO_NEWLOCALS; if (ste->ste_type == FunctionBlock) { - flags |= CO_NEWLOCALS | CO_OPTIMIZED; + if (!ste->ste_unoptimized) + flags |= CO_OPTIMIZED; if (ste->ste_nested) flags |= CO_NESTED; - if (ste->ste_generator && !ste->ste_coroutine) + if (ste->ste_generator) flags |= CO_GENERATOR; - if (!ste->ste_generator && ste->ste_coroutine) - flags |= CO_COROUTINE; - if (ste->ste_generator && ste->ste_coroutine) - flags |= CO_ASYNC_GENERATOR; if (ste->ste_varargs) flags |= CO_VARARGS; if (ste->ste_varkeywords) @@ -5858,44 +3786,21 @@ compute_code_flags(struct compiler *c) /* (Only) inherit compilerflags in PyCF_MASK */ flags |= (c->c_flags->cf_flags & PyCF_MASK); - if ((c->c_flags->cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT) && - ste->ste_coroutine && - !ste->ste_generator) { - flags |= CO_COROUTINE; + 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; } -// Merge *tuple* with constant cache. -// Unlike merge_consts_recursive(), this function doesn't work recursively. -static int -merge_const_tuple(struct compiler *c, PyObject **tuple) -{ - assert(PyTuple_CheckExact(*tuple)); - - PyObject *key = _PyCode_ConstantKey(*tuple); - if (key == NULL) { - return 0; - } - - // t is borrowed reference - PyObject *t = PyDict_SetDefault(c->c_const_cache, key, key); - Py_DECREF(key); - if (t == NULL) { - return 0; - } - if (t == key) { // tuple is new constant. - return 1; - } - - PyObject *u = PyTuple_GET_ITEM(t, 1); - Py_INCREF(u); - Py_DECREF(*tuple); - *tuple = u; - return 1; -} - static PyCodeObject * makecode(struct compiler *c, struct assembler *a) { @@ -5904,16 +3809,19 @@ makecode(struct compiler *c, struct assembler *a) PyObject *consts = NULL; PyObject *names = NULL; PyObject *varnames = NULL; + PyObject *filename = NULL; PyObject *name = NULL; PyObject *freevars = NULL; PyObject *cellvars = NULL; PyObject *bytecode = NULL; - Py_ssize_t nlocals; - int nlocals_int; - int flags; - int posorkeywordargcount, posonlyargcount, kwonlyargcount, maxdepth; + 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); - consts = consts_dict_keys_inorder(c->u->u_consts); names = dict_keys_inorder(c->u->u_names, 0); varnames = dict_keys_inorder(c->u->u_varnames, 0); if (!consts || !names || !varnames) @@ -5922,22 +3830,14 @@ makecode(struct compiler *c, struct assembler *a) cellvars = dict_keys_inorder(c->u->u_cellvars, 0); if (!cellvars) goto error; - freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_GET_SIZE(cellvars)); + freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - - if (!merge_const_tuple(c, &names) || - !merge_const_tuple(c, &varnames) || - !merge_const_tuple(c, &cellvars) || - !merge_const_tuple(c, &freevars)) - { + filename = PyString_FromString(c->c_filename); + if (!filename) goto error; - } - - nlocals = PyDict_GET_SIZE(c->u->u_varnames); - assert(nlocals < INT_MAX); - nlocals_int = Py_SAFE_DOWNCAST(nlocals, Py_ssize_t, int); + nlocals = PyDict_Size(c->u->u_varnames); flags = compute_code_flags(c); if (flags < 0) goto error; @@ -5951,26 +3851,18 @@ makecode(struct compiler *c, struct assembler *a) goto error; Py_DECREF(consts); consts = tmp; - if (!merge_const_tuple(c, &consts)) { - goto error; - } - posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int); - posorkeywordargcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int); - kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int); - maxdepth = stackdepth(c); - if (maxdepth < 0) { - goto error; - } - co = PyCode_NewWithPosOnlyArgs(posonlyargcount+posorkeywordargcount, - posonlyargcount, kwonlyargcount, nlocals_int, - maxdepth, flags, bytecode, consts, names, - varnames, freevars, cellvars, c->c_filename, - c->u->u_name, c->u->u_firstlineno, a->a_lnotab); + co = PyCode_New(c->u->u_argcount, 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); @@ -5989,9 +3881,9 @@ dump_instr(const struct instr *i) char arg[128]; *arg = '\0'; - if (HAS_ARG(i->i_opcode)) { + 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); } @@ -6028,7 +3920,7 @@ assemble(struct compiler *c, int addNone) if (!c->u->u_curblock->b_return) { NEXT_BLOCK(c); if (addNone) - ADDOP_LOAD_CONST(c, Py_None); + ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP(c, RETURN_VALUE); } @@ -6041,14 +3933,14 @@ assemble(struct compiler *c, int addNone) /* Set firstlineno if it wasn't explicitly set. */ if (!c->u->u_firstlineno) { - if (entryblock && entryblock->b_instr && entryblock->b_instr->i_lineno) + 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, nblocks); + dfs(c, entryblock, &a); /* Can't modify the bytecode after computing jump offsets. */ assemble_jump_offsets(&a, c); @@ -6061,9 +3953,9 @@ assemble(struct compiler *c, int addNone) goto error; } - if (_PyBytes_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) + if (_PyString_Resize(&a.a_lnotab, a.a_lnotab_off) < 0) goto error; - if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0) + if (_PyString_Resize(&a.a_bytecode, a.a_offset) < 0) goto error; co = makecode(c, &a); @@ -6071,11 +3963,3 @@ assemble(struct compiler *c, int addNone) assemble_free(&a); return co; } - -#undef PyAST_Compile -PyCodeObject * -PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags, - PyArena *arena) -{ - return PyAST_CompileEx(mod, filename, flags, -1, arena); -} |