📄 ceval.c
字号:
PUSH(x);
break;
}
case BUILD_SLICE:
if (oparg == 3)
w = POP();
else
w = NULL;
v = POP();
u = POP();
x = PySlice_New(u, v, w);
Py_DECREF(u);
Py_DECREF(v);
Py_XDECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case EXTENDED_ARG:
opcode = NEXTOP();
oparg = oparg<<16 | NEXTARG();
goto dispatch_opcode;
default:
fprintf(stderr,
"XXX lineno: %d, opcode: %d\n",
f->f_lineno, opcode);
PyErr_SetString(PyExc_SystemError, "unknown opcode");
why = WHY_EXCEPTION;
break;
#ifdef CASE_TOO_BIG
}
#endif
} /* switch */
on_error:
/* Quickly continue if no error occurred */
if (why == WHY_NOT) {
if (err == 0 && x != NULL) {
#ifdef CHECKEXC
/* This check is expensive! */
if (PyErr_Occurred())
fprintf(stderr,
"XXX undetected error\n");
else
#endif
continue; /* Normal, fast path */
}
why = WHY_EXCEPTION;
x = Py_None;
err = 0;
}
/* Double-check exception status */
if (why == WHY_EXCEPTION || why == WHY_RERAISE) {
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_SystemError,
"error return without exception set");
why = WHY_EXCEPTION;
}
}
#ifdef CHECKEXC
else {
/* This check is expensive! */
if (PyErr_Occurred()) {
fprintf(stderr,
"XXX undetected error (why=%d)\n",
why);
why = WHY_EXCEPTION;
}
}
#endif
/* Log traceback info if this is a real exception */
if (why == WHY_EXCEPTION) {
f->f_lasti = INSTR_OFFSET() - 1;
if (HAS_ARG(opcode))
f->f_lasti -= 2;
PyTraceBack_Here(f);
if (tstate->c_tracefunc != NULL)
call_exc_trace(tstate->c_tracefunc,
tstate->c_traceobj, f);
}
/* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
if (why == WHY_RERAISE)
why = WHY_EXCEPTION;
/* Unwind stacks if a (pseudo) exception occurred */
while (why != WHY_NOT && why != WHY_YIELD && f->f_iblock > 0) {
PyTryBlock *b = PyFrame_BlockPop(f);
if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) {
/* For a continue inside a try block,
don't pop the block for the loop. */
PyFrame_BlockSetup(f, b->b_type, b->b_handler,
b->b_level);
why = WHY_NOT;
JUMPTO(PyInt_AS_LONG(retval));
Py_DECREF(retval);
break;
}
while (STACK_LEVEL() > b->b_level) {
v = POP();
Py_XDECREF(v);
}
if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
why = WHY_NOT;
JUMPTO(b->b_handler);
break;
}
if (b->b_type == SETUP_FINALLY ||
(b->b_type == SETUP_EXCEPT &&
why == WHY_EXCEPTION)) {
if (why == WHY_EXCEPTION) {
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
if (val == NULL) {
val = Py_None;
Py_INCREF(val);
}
/* Make the raw exception data
available to the handler,
so a program can emulate the
Python main loop. Don't do
this for 'finally'. */
if (b->b_type == SETUP_EXCEPT) {
PyErr_NormalizeException(
&exc, &val, &tb);
set_exc_info(tstate,
exc, val, tb);
}
if (tb == NULL) {
Py_INCREF(Py_None);
PUSH(Py_None);
} else
PUSH(tb);
PUSH(val);
PUSH(exc);
}
else {
if (why == WHY_RETURN ||
why == WHY_CONTINUE)
PUSH(retval);
v = PyInt_FromLong((long)why);
PUSH(v);
}
why = WHY_NOT;
JUMPTO(b->b_handler);
break;
}
} /* unwind stack */
/* End the loop if we still have an error (or return) */
if (why != WHY_NOT)
break;
} /* main loop */
if (why != WHY_YIELD) {
/* Pop remaining stack entries -- but when yielding */
while (!STACK_EMPTY()) {
v = POP();
Py_XDECREF(v);
}
}
if (why != WHY_RETURN && why != WHY_YIELD)
retval = NULL;
if (tstate->use_tracing) {
if (tstate->c_tracefunc
&& (why == WHY_RETURN || why == WHY_YIELD)) {
if (call_trace(tstate->c_tracefunc,
tstate->c_traceobj, f,
PyTrace_RETURN, retval)) {
Py_XDECREF(retval);
retval = NULL;
why = WHY_EXCEPTION;
}
}
if (tstate->c_profilefunc) {
if (why == WHY_EXCEPTION)
call_trace_protected(tstate->c_profilefunc,
tstate->c_profileobj, f,
PyTrace_RETURN);
else if (call_trace(tstate->c_profilefunc,
tstate->c_profileobj, f,
PyTrace_RETURN, retval)) {
Py_XDECREF(retval);
retval = NULL;
why = WHY_EXCEPTION;
}
}
}
reset_exc_info(tstate);
/* pop frame */
--tstate->recursion_depth;
tstate->frame = f->f_back;
return retval;
#undef PYTHON_GLOBALS
#define PYTHON_GLOBALS (SPy_get_globals())
}
DL_EXPORT(PyObject *)
PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyObject **args, int argcount, PyObject **kws, int kwcount,
PyObject **defs, int defcount, PyObject *closure)
{
register PyFrameObject *f;
register PyObject *retval = NULL;
register PyObject **fastlocals, **freevars;
PyThreadState *tstate = PyThreadState_GET();
PyObject *x, *u;
if (globals == NULL) {
PyErr_SetString(PyExc_SystemError,
"PyEval_EvalCodeEx: NULL globals");
return NULL;
}
f = PyFrame_New(tstate, /*back*/
co, /*code*/
globals, locals);
if (f == NULL)
return NULL;
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + f->f_nlocals;
if (co->co_argcount > 0 ||
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
int i;
int n = argcount;
PyObject *kwdict = NULL;
if (co->co_flags & CO_VARKEYWORDS) {
kwdict = PyDict_New();
if (kwdict == NULL)
goto fail;
i = co->co_argcount;
if (co->co_flags & CO_VARARGS)
i++;
SETLOCAL(i, kwdict);
}
if (argcount > co->co_argcount) {
if (!(co->co_flags & CO_VARARGS)) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes %s %d "
"%sargument%s (%d given)",
PyString_AsString(co->co_name),
defcount ? "at most" : "exactly",
co->co_argcount,
kwcount ? "non-keyword " : "",
co->co_argcount == 1 ? "" : "s",
argcount);
goto fail;
}
n = co->co_argcount;
}
for (i = 0; i < n; i++) {
x = args[i];
Py_INCREF(x);
SETLOCAL(i, x);
}
if (co->co_flags & CO_VARARGS) {
u = PyTuple_New(argcount - n);
if (u == NULL)
goto fail;
SETLOCAL(co->co_argcount, u);
for (i = n; i < argcount; i++) {
x = args[i];
Py_INCREF(x);
PyTuple_SET_ITEM(u, i-n, x);
}
}
for (i = 0; i < kwcount; i++) {
PyObject *keyword = kws[2*i];
PyObject *value = kws[2*i + 1];
int j;
if (keyword == NULL || !PyString_Check(keyword)) {
PyErr_Format(PyExc_TypeError,
"%.200s() keywords must be strings",
PyString_AsString(co->co_name));
goto fail;
}
/* XXX slow -- speed up using dictionary? */
for (j = 0; j < co->co_argcount; j++) {
PyObject *nm = PyTuple_GET_ITEM(
co->co_varnames, j);
int cmp = PyObject_RichCompareBool(
keyword, nm, Py_EQ);
if (cmp > 0)
break;
else if (cmp < 0)
goto fail;
}
/* Check errors from Compare */
if (PyErr_Occurred())
goto fail;
if (j >= co->co_argcount) {
if (kwdict == NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s() got an unexpected "
"keyword argument '%.400s'",
PyString_AsString(co->co_name),
PyString_AsString(keyword));
goto fail;
}
PyDict_SetItem(kwdict, keyword, value);
}
else {
if (GETLOCAL(j) != NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s() got multiple "
"values for keyword "
"argument '%.400s'",
PyString_AsString(co->co_name),
PyString_AsString(keyword));
goto fail;
}
Py_INCREF(value);
SETLOCAL(j, value);
}
}
if (argcount < co->co_argcount) {
int m = co->co_argcount - defcount;
for (i = argcount; i < m; i++) {
if (GETLOCAL(i) == NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes %s %d "
"%sargument%s (%d given)",
PyString_AsString(co->co_name),
((co->co_flags & CO_VARARGS) ||
defcount) ? "at least"
: "exactly",
m, kwcount ? "non-keyword " : "",
m == 1 ? "" : "s", i);
goto fail;
}
}
if (n > m)
i = n - m;
else
i = 0;
for (; i < defcount; i++) {
if (GETLOCAL(m+i) == NULL) {
PyObject *def = defs[i];
Py_INCREF(def);
SETLOCAL(m+i, def);
}
}
}
}
else {
if (argcount > 0 || kwcount > 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%d given)",
PyString_AsString(co->co_name),
argcount + kwcount);
goto fail;
}
}
/* Allocate and initialize storage for cell vars, and copy free
vars into frame. This isn't too efficient right now. */
if (f->f_ncells) {
int i = 0, j = 0, nargs, found;
char *cellname, *argname;
PyObject *c;
nargs = co->co_argcount;
if (co->co_flags & CO_VARARGS)
nargs++;
if (co->co_flags & CO_VARKEYWORDS)
nargs++;
/* Check for cells that shadow args */
for (i = 0; i < f->f_ncells && j < nargs; ++i) {
cellname = PyString_AS_STRING(
PyTuple_GET_ITEM(co->co_cellvars, i));
found = 0;
while (j < nargs) {
argname = PyString_AS_STRING(
PyTuple_GET_ITEM(co->co_varnames, j));
if (strcmp(cellname, argname) == 0) {
c = PyCell_New(GETLOCAL(j));
if (c == NULL)
goto fail;
GETLOCAL(f->f_nlocals + i) = c;
found = 1;
break;
}
j++;
}
if (found == 0) {
c = PyCell_New(NULL);
if (c == NULL)
goto fail;
SETLOCAL(f->f_nlocals + i, c);
}
}
/* Initialize any that are left */
while (i < f->f_ncells) {
c = PyCell_New(NULL);
if (c == NULL)
goto fail;
SETLOCAL(f->f_nlocals + i, c);
i++;
}
}
if (f->f_nfreevars) {
int i;
for (i = 0; i < f->f_nfreevars; ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);
Py_INCREF(o);
freevars[f->f_ncells + i] = o;
}
}
if (co->co_flags & CO_GENERATOR) {
/* Don't need to keep the reference to f_back, it will be set
* when the generator is resumed. */
Py_XDECREF(f->f_back);
f->f_back = NULL;
/* Create a new generator that owns the ready to run frame
* and return that as the value. */
return gen_new(f);
}
retval = eval_frame(f);
fail: /* Jump here from prelude on failure */
/* decref'ing the frame can cause __del__ methods to get invoked,
which can call back into Python. While we're done with the
current Python frame (f), the associated C stack is still in use,
so recursion_depth must be boosted for the duration.
*/
assert(tstate != NULL);
++tstate->recursion_depth;
Py_DECREF(f);
--tstate->recursion_depth;
return retval;
}
static void
set_exc_info(PyThreadState *tstate,
PyObject *type, PyObject *value, PyObject *tb)
{
PyFrameObject *frame;
PyObject *tmp_type, *tmp_value, *tmp_tb;
frame = tstate->frame;
if (frame->f_exc_type == NULL) {
/* This frame didn't catch an exception before */
/* Save previous exception of this thread in this frame */
if (tstate->exc_type == NULL) {
Py_INCREF(Py_None);
tstate->exc_type = Py_None;
}
tmp_type = frame->f_exc_type;
tmp_value = frame->f_exc_value;
tmp_tb = frame->f_exc_traceback;
Py_XINCREF(tstate->exc_type);
Py_XINCREF(tstate->exc_value);
Py_XINCREF(tstate->exc_traceback);
frame->f_exc_type = tstate->exc_type;
frame->f_exc_value = tstate->exc_value;
frame->f_exc_traceback = tstate->exc_traceback;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
/* Set new exception for this thread */
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
Py_XINCREF(type);
Py_XINCREF(value);
Py_XINCREF(tb);
tstate->exc_type = type;
tstate->exc_value = value;
tstate->exc_traceback = tb;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
/* For b/w compatibility */
PySys_SetObject("exc_type", type);
PySys_SetObject("exc_value", value);
PySys_SetObject("exc_traceback", tb);
}
static void
reset_exc_info(PyThreadState *tstate)
{
PyFrameObject *frame;
PyObject *tmp_type, *tmp_value, *tmp_tb;
frame = tstate->frame;
if (frame->f_exc_type != NULL) {
/* This frame caught an exception */
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
Py_XINCREF(frame->f_exc_type);
Py_XINCREF(frame->f_exc_value);
Py_XINCREF(frame->f_exc_traceback);
tstate->exc_type = frame->f_exc_type;
tstate->exc_value = frame->f_exc_value;
tstate->exc_traceback = frame->f_exc_traceback;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
/* For b/w compatibility */
PySys_SetObject("exc_type", frame->f_exc_type);
PySys_SetObject("exc_value", frame->f_exc_value);
PySys_SetObject("exc_traceback", frame->f_exc_traceback);
}
tmp_type = frame->f_exc_type;
tmp_value = frame->f_exc_value;
tmp_tb = frame->f_exc_traceback;
frame->f_exc_type = NULL;
frame->f_exc_value = NULL;
frame->f_exc_traceback = NULL;
Py_XDECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
/* Logic for the raise statement (too complicated for inlining).
This *consumes* a reference count to each of its arguments. */
static enum why_code
do_raise(PyObject *type, PyObject *value, PyObject *tb)
{
if (type == NULL) {
/* Reraise */
PyThreadState *tstate = PyThreadState_Get();
type = tstate->exc_type == NULL ? Py_None : tstate->exc_type;
value = tstate->exc_valu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -