Commit 64204de0 authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #27095: Simplified MAKE_FUNCTION and removed MAKE_CLOSURE opcodes.

Patch by Demur Rumed.
parent 5697c4b6
......@@ -937,27 +937,16 @@ All of the following opcodes use their arguments.
.. opcode:: MAKE_FUNCTION (argc)
Pushes a new function object on the stack. From bottom to top, the consumed
stack must consist of
* ``argc & 0xFF`` default argument objects in positional order
* ``(argc >> 8) & 0xFF`` pairs of name and default argument, with the name
just below the object on the stack, for keyword-only parameters
* ``(argc >> 16) & 0x7FFF`` parameter annotation objects
* a tuple listing the parameter names for the annotations (only if there are
ony annotation objects)
stack must consist of values if the argument carries a specified flag value
* ``0x01`` a tuple of default argument objects in positional order
* ``0x02`` a dictionary of keyword-only parameters' default values
* ``0x04`` an annotation dictionary
* ``0x08`` a tuple containing cells for free variables, making a closure
* the code associated with the function (at TOS1)
* the :term:`qualified name` of the function (at TOS)
.. opcode:: MAKE_CLOSURE (argc)
Creates a new function object, sets its *__closure__* slot, and pushes it on
the stack. TOS is the :term:`qualified name` of the function, TOS1 is the
code associated with the function, and TOS2 is the tuple containing cells for
the closure's free variables. *argc* is interpreted as in ``MAKE_FUNCTION``;
the annotations and defaults are also in the same order below TOS2.
.. opcode:: BUILD_SLICE (argc)
.. index:: builtin: slice
......
......@@ -102,7 +102,6 @@ extern "C" {
#define CALL_FUNCTION 131
#define MAKE_FUNCTION 132
#define BUILD_SLICE 133
#define MAKE_CLOSURE 134
#define LOAD_CLOSURE 135
#define LOAD_DEREF 136
#define STORE_DEREF 137
......
......@@ -222,8 +222,10 @@ _code_type = type(_write_atomic.__code__)
# Python 3.5.2 3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286)
# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483
# Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed)
# Python 3.6a0 3370 (16 bit wordcode)
# Python 3.6a0 3371 (add BUILD_CONST_KEY_MAP opcode #27140)
# Python 3.6a1 3370 (16 bit wordcode)
# Python 3.6a1 3371 (add BUILD_CONST_KEY_MAP opcode #27140)
# Python 3.6a1 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE
#27095)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
......@@ -232,7 +234,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
MAGIC_NUMBER = (3371).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3372).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'
......
......@@ -319,7 +319,7 @@ class GrammarTests(unittest.TestCase):
def f(x) -> list: pass
self.assertEquals(f.__annotations__, {'return': list})
# test MAKE_CLOSURE with a variety of oparg's
# test closures with a variety of oparg's
closure = 1
def f(): return closure
def f(x=1): return closure
......
......@@ -173,9 +173,8 @@ haslocal.append(126)
def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)
hasnargs.append(131)
def_op('MAKE_FUNCTION', 132) # Number of args with default values
def_op('MAKE_FUNCTION', 132) # Flags
def_op('BUILD_SLICE', 133) # Number of items
def_op('MAKE_CLOSURE', 134)
def_op('LOAD_CLOSURE', 135)
hasfree.append(135)
def_op('LOAD_DEREF', 136)
......
......@@ -649,50 +649,48 @@ expected_jumpy_line = 1
Instruction = dis.Instruction
expected_opinfo_outer = [
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=3, argrepr='3', offset=0, starts_line=2, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='a', argrepr='a', offset=4, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='b', argrepr='b', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=8, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_f, argrepr=repr(code_object_f), offset=10, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f', argrepr="'outer.<locals>.f'", offset=12, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CLOSURE', opcode=134, arg=2, argval=2, argrepr='', offset=14, starts_line=None, is_jump_target=False),
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=16, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=18, starts_line=7, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=20, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=22, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval='', argrepr="''", offset=24, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval=1, argrepr='1', offset=26, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=30, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=32, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='7 positional, 0 keyword pair', offset=34, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=38, starts_line=8, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=40, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval=(3, 4), argrepr='(3, 4)', offset=0, starts_line=2, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_f, argrepr=repr(code_object_f), offset=8, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f', argrepr="'outer.<locals>.f'", offset=10, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='', offset=12, starts_line=None, is_jump_target=False),
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=14, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=16, starts_line=7, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='a', argrepr='a', offset=18, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='b', argrepr='b', offset=20, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval='', argrepr="''", offset=22, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval=1, argrepr='1', offset=24, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=26, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=28, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval='Hello world!', argrepr="'Hello world!'", offset=30, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=7, argval=7, argrepr='7 positional, 0 keyword pair', offset=32, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=36, starts_line=8, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False),
]
expected_opinfo_f = [
Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=5, argrepr='5', offset=0, starts_line=3, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=6, argrepr='6', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=2, argval='a', argrepr='a', offset=4, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=3, argval='b', argrepr='b', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='c', argrepr='c', offset=8, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='d', argrepr='d', offset=10, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=12, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=14, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f.<locals>.inner', argrepr="'outer.<locals>.f.<locals>.inner'", offset=16, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CLOSURE', opcode=134, arg=2, argval=2, argrepr='', offset=18, starts_line=None, is_jump_target=False),
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=20, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=22, starts_line=5, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='a', argrepr='a', offset=24, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=26, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=28, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=30, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='4 positional, 0 keyword pair', offset=32, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=36, starts_line=6, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=(5, 6), argrepr='(5, 6)', offset=0, starts_line=3, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=2, argval='a', argrepr='a', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=3, argval='b', argrepr='b', offset=4, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=0, argval='c', argrepr='c', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=135, arg=1, argval='d', argrepr='d', offset=8, starts_line=None, is_jump_target=False),
Instruction(opname='BUILD_TUPLE', opcode=102, arg=4, argval=4, argrepr='', offset=10, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=code_object_inner, argrepr=repr(code_object_inner), offset=12, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='outer.<locals>.f.<locals>.inner', argrepr="'outer.<locals>.f.<locals>.inner'", offset=14, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_FUNCTION', opcode=132, arg=9, argval=9, argrepr='', offset=16, starts_line=None, is_jump_target=False),
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=18, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=20, starts_line=5, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=2, argval='a', argrepr='a', offset=22, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=3, argval='b', argrepr='b', offset=24, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=0, argval='c', argrepr='c', offset=26, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_DEREF', opcode=136, arg=1, argval='d', argrepr='d', offset=28, starts_line=None, is_jump_target=False),
Instruction(opname='CALL_FUNCTION', opcode=131, arg=4, argval=4, argrepr='4 positional, 0 keyword pair', offset=30, starts_line=None, is_jump_target=False),
Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=32, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=34, starts_line=6, is_jump_target=False),
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=36, starts_line=None, is_jump_target=False),
]
expected_opinfo_inner = [
......
......@@ -345,7 +345,7 @@ class GrammarTests(unittest.TestCase):
def f(x) -> list: pass
self.assertEqual(f.__annotations__, {'return': list})
# test MAKE_CLOSURE with a variety of oparg's
# test closures with a variety of opargs
closure = 1
def f(): return closure
def f(x=1): return closure
......
......@@ -10,6 +10,9 @@ What's New in Python 3.6.0 alpha 2
Core and Builtins
-----------------
- Issue #27095: Simplified MAKE_FUNCTION and removed MAKE_CLOSURE opcodes.
Patch by Demur Rumed.
- Issue #27190: Raise NotSupportedError if sqlite3 is older than 3.3.1.
Patch by Dave Sawyer.
......
......@@ -3325,116 +3325,36 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
TARGET(MAKE_CLOSURE)
TARGET(MAKE_FUNCTION) {
int posdefaults = oparg & 0xff;
int kwdefaults = (oparg>>8) & 0xff;
int num_annotations = (oparg >> 16) & 0x7fff;
PyObject *qualname = POP(); /* qualname */
PyObject *code = POP(); /* code object */
PyObject *func = PyFunction_NewWithQualName(code, f->f_globals, qualname);
Py_DECREF(code);
Py_DECREF(qualname);
PyObject *qualname = POP();
PyObject *codeobj = POP();
PyFunctionObject *func = (PyFunctionObject *)
PyFunction_NewWithQualName(codeobj, f->f_globals, qualname);
if (func == NULL)
Py_DECREF(codeobj);
Py_DECREF(qualname);
if (func == NULL) {
goto error;
if (opcode == MAKE_CLOSURE) {
PyObject *closure = POP();
if (PyFunction_SetClosure(func, closure) != 0) {
/* Can't happen unless bytecode is corrupt. */
Py_DECREF(func);
Py_DECREF(closure);
goto error;
}
Py_DECREF(closure);
}
if (num_annotations > 0) {
Py_ssize_t name_ix;
PyObject *names = POP(); /* names of args with annotations */
PyObject *anns = PyDict_New();
if (anns == NULL) {
Py_DECREF(func);
Py_DECREF(names);
goto error;
}
name_ix = PyTuple_Size(names);
assert(num_annotations == name_ix+1);
while (name_ix > 0) {
PyObject *name, *value;
int err;
--name_ix;
name = PyTuple_GET_ITEM(names, name_ix);
value = POP();
err = PyDict_SetItem(anns, name, value);
Py_DECREF(value);
if (err != 0) {
Py_DECREF(anns);
Py_DECREF(func);
Py_DECREF(names);
goto error;
}
}
Py_DECREF(names);
if (PyFunction_SetAnnotations(func, anns) != 0) {
/* Can't happen unless
PyFunction_SetAnnotations changes. */
Py_DECREF(anns);
Py_DECREF(func);
goto error;
}
Py_DECREF(anns);
if (oparg & 0x08) {
assert(PyTuple_CheckExact(TOP()));
func ->func_closure = POP();
}
/* XXX Maybe this should be a separate opcode? */
if (kwdefaults > 0) {
PyObject *defs = PyDict_New();
if (defs == NULL) {
Py_DECREF(func);
goto error;
}
while (--kwdefaults >= 0) {
PyObject *v = POP(); /* default value */
PyObject *key = POP(); /* kw only arg name */
int err = PyDict_SetItem(defs, key, v);
Py_DECREF(v);
Py_DECREF(key);
if (err != 0) {
Py_DECREF(defs);
Py_DECREF(func);
goto error;
}
}
if (PyFunction_SetKwDefaults(func, defs) != 0) {
/* Can't happen unless
PyFunction_SetKwDefaults changes. */
Py_DECREF(func);
Py_DECREF(defs);
goto error;
}
Py_DECREF(defs);
if (oparg & 0x04) {
assert(PyDict_CheckExact(TOP()));
func->func_annotations = POP();
}
if (posdefaults > 0) {
PyObject *defs = PyTuple_New(posdefaults);
if (defs == NULL) {
Py_DECREF(func);
goto error;
}
while (--posdefaults >= 0)
PyTuple_SET_ITEM(defs, posdefaults, POP());
if (PyFunction_SetDefaults(func, defs) != 0) {
/* Can't happen unless
PyFunction_SetDefaults changes. */
Py_DECREF(defs);
Py_DECREF(func);
goto error;
}
Py_DECREF(defs);
if (oparg & 0x02) {
assert(PyDict_CheckExact(TOP()));
func->func_kwdefaults = POP();
}
if (oparg & 0x01) {
assert(PyTuple_CheckExact(TOP()));
func->func_defaults = POP();
}
PUSH(func);
PUSH((PyObject *)func);
DISPATCH();
}
......
......@@ -1030,11 +1030,10 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return -NARGS(oparg)-1;
case CALL_FUNCTION_VAR_KW:
return -NARGS(oparg)-2;
case MAKE_FUNCTION:
return -1 -NARGS(oparg) - ((oparg >> 16) & 0xffff);
case MAKE_CLOSURE:
return -2 - NARGS(oparg) - ((oparg >> 16) & 0xffff);
#undef NARGS
case MAKE_FUNCTION:
return -1 - ((oparg & 0x01) != 0) - ((oparg & 0x02) != 0) -
((oparg & 0x04) != 0) - ((oparg & 0x08) != 0);
case BUILD_SLICE:
if (oparg == 3)
return -2;
......@@ -1472,53 +1471,50 @@ compiler_lookup_arg(PyObject *dict, PyObject *name)
}
static int
compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t args, PyObject *qualname)
compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, PyObject *qualname)
{
Py_ssize_t i, free = PyCode_GetNumFree(co);
if (qualname == NULL)
qualname = co->co_name;
if (free == 0) {
ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
ADDOP_O(c, LOAD_CONST, qualname, consts);
ADDOP_I(c, MAKE_FUNCTION, args);
return 1;
}
for (i = 0; i < free; ++i) {
/* Bypass com_addop_varname because it will generate
LOAD_DEREF but LOAD_CLOSURE is needed.
*/
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
int arg, reftype;
/* Special case: If a class contains a method with a
free variable that has the same name as a method,
the name will be considered free *and* local in the
class. It should be handled by the closure, as
well as by the normal name loookup logic.
*/
reftype = get_ref_type(c, name);
if (reftype == CELL)
arg = compiler_lookup_arg(c->u->u_cellvars, name);
else /* (reftype == FREE) */
arg = compiler_lookup_arg(c->u->u_freevars, name);
if (arg == -1) {
fprintf(stderr,
"lookup %s in %s %d %d\n"
"freevars of %s: %s\n",
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()");
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 loookup logic.
*/
reftype = get_ref_type(c, name);
if (reftype == CELL)
arg = compiler_lookup_arg(c->u->u_cellvars, name);
else /* (reftype == FREE) */
arg = compiler_lookup_arg(c->u->u_freevars, name);
if (arg == -1) {
fprintf(stderr,
"lookup %s in %s %d %d\n"
"freevars of %s: %s\n",
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);
}
ADDOP_I(c, LOAD_CLOSURE, arg);
flags |= 0x08;
ADDOP_I(c, BUILD_TUPLE, free);
}
ADDOP_I(c, BUILD_TUPLE, free);
ADDOP_O(c, LOAD_CONST, (PyObject*)co, consts);
ADDOP_O(c, LOAD_CONST, qualname, consts);
ADDOP_I(c, MAKE_CLOSURE, args);
ADDOP_I(c, MAKE_FUNCTION, flags);
return 1;
}
......@@ -1536,27 +1532,59 @@ compiler_decorators(struct compiler *c, asdl_seq* decos)
return 1;
}
static int
static Py_ssize_t
compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs,
asdl_seq *kw_defaults)
{
int i, default_count = 0;
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)
return -1;
ADDOP_O(c, LOAD_CONST, mangled, consts);
Py_DECREF(mangled);
if (!mangled) {
goto error;
}
if (keys == NULL) {
keys = PyList_New(1);
if (keys == NULL) {
Py_DECREF(mangled);
return -1;
}
PyList_SET_ITEM(keys, 0, mangled);
}
else {
int res = PyList_Append(keys, mangled);
Py_DECREF(mangled);
if (res == -1) {
goto error;
}
}
if (!compiler_visit_expr(c, default_)) {
return -1;
goto error;
}
default_count++;
}
}
return default_count;
if (keys != NULL) {
Py_ssize_t default_count = PyList_GET_SIZE(keys);
PyObject *keys_tuple = PyList_AsTuple(keys);
Py_DECREF(keys);
if (keys_tuple == NULL) {
return -1;
}
ADDOP_N(c, LOAD_CONST, keys_tuple, consts);
ADDOP_I(c, BUILD_CONST_KEY_MAP, default_count);
return default_count;
}
else {
return 0;
}
error:
Py_XDECREF(keys);
return -1;
}
static int
......@@ -1595,15 +1623,14 @@ compiler_visit_argannotations(struct compiler *c, asdl_seq* args,
return 1;
}
static int
static Py_ssize_t
compiler_visit_annotations(struct compiler *c, arguments_ty args,
expr_ty returns)
{
/* Push arg annotations and a list of the argument names. Return the #
of items pushed. The expressions are evaluated out-of-order wrt the
source code.
/* Push arg annotation dict. Return # of items pushed.
The expressions are evaluated out-of-order wrt the source code.
More than 2^16-1 annotations is a SyntaxError. Returns -1 on error.
Returns -1 on error.
*/
static identifier return_str;
PyObject *names;
......@@ -1635,38 +1662,47 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args,
}
len = PyList_GET_SIZE(names);
if (len > 65534) {
/* len must fit in 16 bits, and len is incremented below */
PyErr_SetString(PyExc_SyntaxError,
"too many annotations");
goto error;
}
if (len) {
/* convert names to a tuple and place on stack */
PyObject *elt;
Py_ssize_t i;
PyObject *s = PyTuple_New(len);
if (!s)
goto error;
for (i = 0; i < len; i++) {
elt = PyList_GET_ITEM(names, i);
Py_INCREF(elt);
PyTuple_SET_ITEM(s, i, elt);
PyObject *keytuple = PyList_AsTuple(names);
Py_DECREF(names);
if (keytuple == NULL) {
return -1;
}
ADDOP_O(c, LOAD_CONST, s, consts);
Py_DECREF(s);
len++; /* include the just-pushed tuple */
ADDOP_N(c, LOAD_CONST, keytuple, consts);
ADDOP_I(c, BUILD_CONST_KEY_MAP, len);
}
Py_DECREF(names);
/* We just checked that len <= 65535, see above */
return Py_SAFE_DOWNCAST(len, Py_ssize_t, int);
else {
Py_DECREF(names);
}
return len;
error:
Py_DECREF(names);
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) {
VISIT_SEQ(c, expr, args->defaults);
ADDOP_I(c, BUILD_TUPLE, asdl_seq_LEN(args->defaults));
funcflags |= 0x01;
}
if (args->kwonlyargs) {
Py_ssize_t 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)
{
......@@ -1678,12 +1714,11 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
asdl_seq* decos;
asdl_seq *body;
stmt_ty st;
Py_ssize_t i, n, arglength;
int docstring, kw_default_count = 0;
Py_ssize_t i, n, funcflags;
int docstring;
int num_annotations;
int scope_type;
if (is_async) {
assert(s->kind == AsyncFunctionDef_kind);
......@@ -1708,24 +1743,23 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
if (!compiler_decorators(c, decos))
return 0;
if (args->defaults)
VISIT_SEQ(c, expr, args->defaults);
if (args->kwonlyargs) {
int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs,
args->kw_defaults);
if (res < 0)
return 0;
kw_default_count = res;
funcflags = compiler_default_arguments(c, args);
if (funcflags == -1) {
return 0;
}
num_annotations = compiler_visit_annotations(c, args, returns);
if (num_annotations < 0)
if (num_annotations < 0) {
return 0;
assert((num_annotations & 0xFFFF) == num_annotations);
}
else if (num_annotations > 0) {
funcflags |= 0x04;
}
if (!compiler_enter_scope(c, name,
scope_type, (void *)s,
s->lineno))
if (!compiler_enter_scope(c, name, scope_type, (void *)s, s->lineno)) {
return 0;
}
st = (stmt_ty)asdl_seq_GET(body, 0);
docstring = compiler_isdocstring(st);
......@@ -1758,12 +1792,9 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
return 0;
}
arglength = asdl_seq_LEN(args->defaults);
arglength |= kw_default_count << 8;
arglength |= num_annotations << 16;
if (is_async)
co->co_flags |= CO_COROUTINE;
compiler_make_closure(c, co, arglength, qualname);
compiler_make_closure(c, co, funcflags, qualname);
Py_DECREF(qualname);
Py_DECREF(co);
......@@ -1923,8 +1954,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
PyCodeObject *co;
PyObject *qualname;
static identifier name;
int kw_default_count = 0;
Py_ssize_t arglength;
Py_ssize_t funcflags;
arguments_ty args = e->v.Lambda.args;
assert(e->kind == Lambda_kind);
......@@ -1934,14 +1964,11 @@ compiler_lambda(struct compiler *c, expr_ty e)
return 0;
}
if (args->defaults)
VISIT_SEQ(c, expr, args->defaults);
if (args->kwonlyargs) {
int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs,
args->kw_defaults);
if (res < 0) return 0;
kw_default_count = res;
funcflags = compiler_default_arguments(c, args);
if (funcflags == -1) {
return 0;
}
if (!compiler_enter_scope(c, name, COMPILER_SCOPE_LAMBDA,
(void *)e, e->lineno))
return 0;
......@@ -1967,9 +1994,7 @@ compiler_lambda(struct compiler *c, expr_ty e)
if (co == NULL)
return 0;
arglength = asdl_seq_LEN(args->defaults);
arglength |= kw_default_count << 8;
compiler_make_closure(c, co, arglength, qualname);
compiler_make_closure(c, co, funcflags, qualname);
Py_DECREF(qualname);
Py_DECREF(co);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -133,7 +133,7 @@ static void *opcode_targets[256] = {
&&TARGET_CALL_FUNCTION,
&&TARGET_MAKE_FUNCTION,
&&TARGET_BUILD_SLICE,
&&TARGET_MAKE_CLOSURE,
&&_unknown_opcode,
&&TARGET_LOAD_CLOSURE,
&&TARGET_LOAD_DEREF,
&&TARGET_STORE_DEREF,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment