summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c293
1 files changed, 256 insertions, 37 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 7656b8ef54..5ee9077332 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -12,8 +12,10 @@
#include "Python.h"
#include "code.h"
+#include "dictobject.h"
#include "frameobject.h"
#include "opcode.h"
+#include "setobject.h"
#include "structmember.h"
#include <ctype.h>
@@ -1504,6 +1506,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
+ TARGET(BINARY_MATRIX_MULTIPLY) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_MatrixMultiply(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
+
TARGET(BINARY_TRUE_DIVIDE) {
PyObject *divisor = POP();
PyObject *dividend = TOP();
@@ -1694,6 +1708,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
+ TARGET(INPLACE_MATRIX_MULTIPLY) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
+
TARGET(INPLACE_TRUE_DIVIDE) {
PyObject *divisor = POP();
PyObject *dividend = TOP();
@@ -2355,6 +2381,43 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
+ TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack)
+ TARGET(BUILD_LIST_UNPACK)
+ _build_list_unpack: {
+ int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK;
+ int i;
+ PyObject *sum = PyList_New(0);
+ PyObject *return_value;
+ if (sum == NULL)
+ goto error;
+
+ for (i = oparg; i > 0; i--) {
+ PyObject *none_val;
+
+ none_val = _PyList_Extend((PyListObject *)sum, PEEK(i));
+ if (none_val == NULL) {
+ Py_DECREF(sum);
+ goto error;
+ }
+ Py_DECREF(none_val);
+ }
+
+ if (convert_to_tuple) {
+ return_value = PyList_AsTuple(sum);
+ Py_DECREF(sum);
+ if (return_value == NULL)
+ goto error;
+ }
+ else {
+ return_value = sum;
+ }
+
+ while (oparg--)
+ Py_DECREF(POP());
+ PUSH(return_value);
+ DISPATCH();
+ }
+
TARGET(BUILD_SET) {
PyObject *set = PySet_New(NULL);
int err = 0;
@@ -2374,14 +2437,127 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
+ TARGET(BUILD_SET_UNPACK) {
+ int i;
+ PyObject *sum = PySet_New(NULL);
+ if (sum == NULL)
+ goto error;
+
+ for (i = oparg; i > 0; i--) {
+ if (_PySet_Update(sum, PEEK(i)) < 0) {
+ Py_DECREF(sum);
+ goto error;
+ }
+ }
+
+ while (oparg--)
+ Py_DECREF(POP());
+ PUSH(sum);
+ DISPATCH();
+ }
+
TARGET(BUILD_MAP) {
PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg);
if (map == NULL)
goto error;
+ while (--oparg >= 0) {
+ int err;
+ PyObject *key = TOP();
+ PyObject *value = SECOND();
+ STACKADJ(-2);
+ err = PyDict_SetItem(map, key, value);
+ Py_DECREF(value);
+ Py_DECREF(key);
+ if (err != 0) {
+ Py_DECREF(map);
+ goto error;
+ }
+ }
PUSH(map);
DISPATCH();
}
+ TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack)
+ TARGET(BUILD_MAP_UNPACK)
+ _build_map_unpack: {
+ int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL;
+ int num_maps;
+ int function_location;
+ int i;
+ PyObject *sum = PyDict_New();
+ if (sum == NULL)
+ goto error;
+ if (with_call) {
+ num_maps = oparg & 0xff;
+ function_location = (oparg>>8) & 0xff;
+ }
+ else {
+ num_maps = oparg;
+ }
+
+ for (i = num_maps; i > 0; i--) {
+ PyObject *arg = PEEK(i);
+ if (with_call) {
+ PyObject *intersection = _PyDictView_Intersect(sum, arg);
+
+ if (intersection == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ PyObject *func = (
+ PEEK(function_location + num_maps));
+ PyErr_Format(PyExc_TypeError,
+ "%.200s%.200s argument after ** "
+ "must be a mapping, not %.200s",
+ PyEval_GetFuncName(func),
+ PyEval_GetFuncDesc(func),
+ arg->ob_type->tp_name);
+ }
+ Py_DECREF(sum);
+ goto error;
+ }
+
+ if (PySet_GET_SIZE(intersection)) {
+ Py_ssize_t idx = 0;
+ PyObject *key;
+ PyObject *func = PEEK(function_location + num_maps);
+ Py_hash_t hash;
+ _PySet_NextEntry(intersection, &idx, &key, &hash);
+ if (!PyUnicode_Check(key)) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s%.200s keywords must be strings",
+ PyEval_GetFuncName(func),
+ PyEval_GetFuncDesc(func));
+ } else {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s%.200s got multiple "
+ "values for keyword argument '%U'",
+ PyEval_GetFuncName(func),
+ PyEval_GetFuncDesc(func),
+ key);
+ }
+ Py_DECREF(intersection);
+ Py_DECREF(sum);
+ goto error;
+ }
+ Py_DECREF(intersection);
+ }
+
+ if (PyDict_Update(sum, arg) < 0) {
+ if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is not a mapping",
+ arg->ob_type->tp_name);
+ }
+ Py_DECREF(sum);
+ goto error;
+ }
+ }
+
+ while (num_maps--)
+ Py_DECREF(POP());
+ PUSH(sum);
+ DISPATCH();
+ }
+
TARGET(STORE_MAP) {
PyObject *key = TOP();
PyObject *value = SECOND();
@@ -3026,6 +3202,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
goto dispatch_opcode;
}
+
#if USE_COMPUTED_GOTOS
_unknown_opcode:
#endif
@@ -3168,8 +3345,7 @@ fast_block_end:
if (why != WHY_RETURN)
retval = NULL;
- assert((retval != NULL && !PyErr_Occurred())
- || (retval == NULL && PyErr_Occurred()));
+ assert((retval != NULL) ^ (PyErr_Occurred() != NULL));
fast_yield:
if (co->co_flags & CO_GENERATOR) {
@@ -3230,7 +3406,7 @@ exit_eval_frame:
f->f_executing = 0;
tstate->frame = f->f_back;
- return retval;
+ return _Py_CheckFunctionResult(NULL, retval, "PyEval_EvalFrameEx");
}
static void
@@ -3387,10 +3563,11 @@ too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlo
PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
-PyObject *
-PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
+static PyObject *
+_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, int argcount, PyObject **kws, int kwcount,
- PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
+ PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure,
+ PyObject *name, PyObject *qualname)
{
PyCodeObject* co = (PyCodeObject*)_co;
PyFrameObject *f;
@@ -3582,7 +3759,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
/* Create a new generator that owns the ready to run frame
* and return that as the value. */
- return PyGen_New(f);
+ return PyGen_NewWithQualName(f, name, qualname);
}
retval = PyEval_EvalFrameEx(f,0);
@@ -3601,6 +3778,16 @@ fail: /* Jump here from prelude on failure */
return retval;
}
+PyObject *
+PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
+ PyObject **args, int argcount, PyObject **kws, int kwcount,
+ PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
+{
+ return _PyEval_EvalCodeWithName(_co, globals, locals,
+ args, argcount, kws, kwcount,
+ defs, defcount, kwdefs, closure,
+ NULL, NULL);
+}
static PyObject *
special_lookup(PyObject *o, _Py_Identifier *id)
@@ -3791,9 +3978,17 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
if (w == NULL) {
/* Iterator done, via error or exhaustion. */
if (!PyErr_Occurred()) {
- PyErr_Format(PyExc_ValueError,
- "need more than %d value%s to unpack",
- i, i == 1 ? "" : "s");
+ if (argcntafter == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "not enough values to unpack (expected %d, got %d)",
+ argcnt, i);
+ }
+ else {
+ PyErr_Format(PyExc_ValueError,
+ "not enough values to unpack "
+ "(expected at least %d, got %d)",
+ argcnt + argcntafter, i);
+ }
}
goto Error;
}
@@ -3810,8 +4005,9 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
return 1;
}
Py_DECREF(w);
- PyErr_Format(PyExc_ValueError, "too many values to unpack "
- "(expected %d)", argcnt);
+ PyErr_Format(PyExc_ValueError,
+ "too many values to unpack (expected %d)",
+ argcnt);
goto Error;
}
@@ -3823,8 +4019,9 @@ unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
ll = PyList_GET_SIZE(l);
if (ll < argcntafter) {
- PyErr_Format(PyExc_ValueError, "need more than %zd values to unpack",
- argcnt + ll);
+ PyErr_Format(PyExc_ValueError,
+ "not enough values to unpack (expected at least %d, got %zd)",
+ argcnt + argcntafter, argcnt + ll);
goto Error;
}
@@ -4086,8 +4283,8 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
#ifdef Py_DEBUG
/* PyEval_CallObjectWithKeywords() must not be called with an exception
- set, because it may clear it (directly or indirectly)
- and so the caller looses its exception */
+ set. It raises a new exception if parameters are invalid or if
+ PyTuple_New() fails, and so the original exception is lost. */
assert(!PyErr_Occurred());
#endif
@@ -4114,8 +4311,6 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
result = PyObject_Call(func, arg, kw);
Py_DECREF(arg);
- assert((result != NULL && !PyErr_Occurred())
- || (result == NULL && PyErr_Occurred()));
return result;
}
@@ -4218,11 +4413,15 @@ call_function(PyObject ***pp_stack, int oparg
PyObject *self = PyCFunction_GET_SELF(func);
if (flags & METH_NOARGS && na == 0) {
C_TRACE(x, (*meth)(self,NULL));
+
+ x = _Py_CheckFunctionResult(func, x, NULL);
}
else if (flags & METH_O && na == 1) {
PyObject *arg = EXT_POP(*pp_stack);
C_TRACE(x, (*meth)(self,arg));
Py_DECREF(arg);
+
+ x = _Py_CheckFunctionResult(func, x, NULL);
}
else {
err_args(func, flags, na);
@@ -4242,7 +4441,8 @@ call_function(PyObject ***pp_stack, int oparg
x = NULL;
}
}
- } else {
+ }
+ else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
/* optimize access to bound methods */
PyObject *self = PyMethod_GET_SELF(func);
@@ -4264,9 +4464,9 @@ call_function(PyObject ***pp_stack, int oparg
x = do_call(func, pp_stack, na, nk);
READ_TIMESTAMP(*pintr1);
Py_DECREF(func);
+
+ assert((x != NULL) ^ (PyErr_Occurred() != NULL));
}
- assert((x != NULL && !PyErr_Occurred())
- || (x == NULL && PyErr_Occurred()));
/* Clear the stack of the function object. Also removes
the arguments in case they weren't consumed already
@@ -4278,8 +4478,7 @@ call_function(PyObject ***pp_stack, int oparg
PCALL(PCALL_POP);
}
- assert((x != NULL && !PyErr_Occurred())
- || (x == NULL && PyErr_Occurred()));
+ assert((x != NULL) ^ (PyErr_Occurred() != NULL));
return x;
}
@@ -4299,6 +4498,8 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
PyObject *globals = PyFunction_GET_GLOBALS(func);
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
+ PyObject *name = ((PyFunctionObject *)func) -> func_name;
+ PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname;
PyObject **d = NULL;
int nd = 0;
@@ -4341,10 +4542,11 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
d = &PyTuple_GET_ITEM(argdefs, 0);
nd = Py_SIZE(argdefs);
}
- return PyEval_EvalCodeEx((PyObject*)co, globals,
- (PyObject *)NULL, (*pp_stack)-n, na,
- (*pp_stack)-2*nk, nk, d, nd, kwdefs,
- PyFunction_GET_CLOSURE(func));
+ return _PyEval_EvalCodeWithName((PyObject*)co, globals,
+ (PyObject *)NULL, (*pp_stack)-n, na,
+ (*pp_stack)-2*nk, nk, d, nd, kwdefs,
+ PyFunction_GET_CLOSURE(func),
+ name, qualname);
}
static PyObject *
@@ -4508,6 +4710,12 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
kwdict = d;
}
}
+ if (nk > 0) {
+ kwdict = update_keyword_args(kwdict, nk, pp_stack, func);
+ if (kwdict == NULL)
+ goto ext_call_fail;
+ }
+
if (flags & CALL_FLAG_VAR) {
stararg = EXT_POP(*pp_stack);
if (!PyTuple_Check(stararg)) {
@@ -4529,11 +4737,6 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
}
nstar = PyTuple_GET_SIZE(stararg);
}
- if (nk > 0) {
- kwdict = update_keyword_args(kwdict, nk, pp_stack, func);
- if (kwdict == NULL)
- goto ext_call_fail;
- }
callargs = update_star_args(na, nstar, stararg, pp_stack);
if (callargs == NULL)
goto ext_call_fail;
@@ -4563,12 +4766,10 @@ ext_call_fail:
Py_XDECREF(callargs);
Py_XDECREF(kwdict);
Py_XDECREF(stararg);
- assert((result != NULL && !PyErr_Occurred())
- || (result == NULL && PyErr_Occurred()));
return result;
}
-/* Extract a slice index from a PyInt or PyLong or an object with the
+/* Extract a slice index from a PyLong or an object with the
nb_index slot defined, and store in *pi.
Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
@@ -4658,11 +4859,29 @@ static PyObject *
import_from(PyObject *v, PyObject *name)
{
PyObject *x;
+ _Py_IDENTIFIER(__name__);
+ PyObject *fullmodname, *pkgname;
x = PyObject_GetAttr(v, name);
- if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (x != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
+ return x;
+ /* Issue #17636: in case this failed because of a circular relative
+ import, try to fallback on reading the module directly from
+ sys.modules. */
+ PyErr_Clear();
+ pkgname = _PyObject_GetAttrId(v, &PyId___name__);
+ if (pkgname == NULL)
+ return NULL;
+ fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name);
+ Py_DECREF(pkgname);
+ if (fullmodname == NULL)
+ return NULL;
+ x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname);
+ if (x == NULL)
PyErr_Format(PyExc_ImportError, "cannot import name %R", name);
- }
+ else
+ Py_INCREF(x);
+ Py_DECREF(fullmodname);
return x;
}