| |
| #define _PY_INTERPRETER |
| |
| #include "Python.h" |
| #include "pycore_frame.h" |
| #include "pycore_runtime.h" |
| #include "pycore_global_objects.h" |
| #include "pycore_intrinsics.h" |
| #include "pycore_pyerrors.h" |
| |
| |
| |
| static PyObject * |
| no_intrinsic(PyThreadState* tstate, PyObject *unused) |
| { |
| _PyErr_SetString(tstate, PyExc_SystemError, "invalid intrinsic function"); |
| return NULL; |
| } |
| |
| static PyObject * |
| print_expr(PyThreadState* tstate, PyObject *value) |
| { |
| PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(displayhook)); |
| // Can't use ERROR_IF here. |
| if (hook == NULL) { |
| _PyErr_SetString(tstate, PyExc_RuntimeError, |
| "lost sys.displayhook"); |
| return NULL; |
| } |
| return PyObject_CallOneArg(hook, value); |
| } |
| |
| static int |
| import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v) |
| { |
| PyObject *all, *dict, *name, *value; |
| int skip_leading_underscores = 0; |
| int pos, err; |
| |
| if (_PyObject_LookupAttr(v, &_Py_ID(__all__), &all) < 0) { |
| return -1; /* Unexpected error */ |
| } |
| if (all == NULL) { |
| if (_PyObject_LookupAttr(v, &_Py_ID(__dict__), &dict) < 0) { |
| return -1; |
| } |
| if (dict == NULL) { |
| _PyErr_SetString(tstate, PyExc_ImportError, |
| "from-import-* object has no __dict__ and no __all__"); |
| return -1; |
| } |
| all = PyMapping_Keys(dict); |
| Py_DECREF(dict); |
| if (all == NULL) |
| return -1; |
| skip_leading_underscores = 1; |
| } |
| |
| for (pos = 0, err = 0; ; pos++) { |
| name = PySequence_GetItem(all, pos); |
| if (name == NULL) { |
| if (!_PyErr_ExceptionMatches(tstate, PyExc_IndexError)) { |
| err = -1; |
| } |
| else { |
| _PyErr_Clear(tstate); |
| } |
| break; |
| } |
| if (!PyUnicode_Check(name)) { |
| PyObject *modname = PyObject_GetAttr(v, &_Py_ID(__name__)); |
| if (modname == NULL) { |
| Py_DECREF(name); |
| err = -1; |
| break; |
| } |
| if (!PyUnicode_Check(modname)) { |
| _PyErr_Format(tstate, PyExc_TypeError, |
| "module __name__ must be a string, not %.100s", |
| Py_TYPE(modname)->tp_name); |
| } |
| else { |
| _PyErr_Format(tstate, PyExc_TypeError, |
| "%s in %U.%s must be str, not %.100s", |
| skip_leading_underscores ? "Key" : "Item", |
| modname, |
| skip_leading_underscores ? "__dict__" : "__all__", |
| Py_TYPE(name)->tp_name); |
| } |
| Py_DECREF(modname); |
| Py_DECREF(name); |
| err = -1; |
| break; |
| } |
| if (skip_leading_underscores) { |
| if (PyUnicode_READY(name) == -1) { |
| Py_DECREF(name); |
| err = -1; |
| break; |
| } |
| if (PyUnicode_READ_CHAR(name, 0) == '_') { |
| Py_DECREF(name); |
| continue; |
| } |
| } |
| value = PyObject_GetAttr(v, name); |
| if (value == NULL) |
| err = -1; |
| else if (PyDict_CheckExact(locals)) |
| err = PyDict_SetItem(locals, name, value); |
| else |
| err = PyObject_SetItem(locals, name, value); |
| Py_DECREF(name); |
| Py_XDECREF(value); |
| if (err < 0) |
| break; |
| } |
| Py_DECREF(all); |
| return err; |
| } |
| |
| static PyObject * |
| import_star(PyThreadState* tstate, PyObject *from) |
| { |
| _PyInterpreterFrame *frame = tstate->cframe->current_frame; |
| if (_PyFrame_FastToLocalsWithError(frame) < 0) { |
| return NULL; |
| } |
| |
| PyObject *locals = frame->f_locals; |
| if (locals == NULL) { |
| _PyErr_SetString(tstate, PyExc_SystemError, |
| "no locals found during 'import *'"); |
| return NULL; |
| } |
| int err = import_all_from(tstate, locals, from); |
| _PyFrame_LocalsToFast(frame, 0); |
| if (err < 0) { |
| return NULL; |
| } |
| Py_RETURN_NONE; |
| } |
| |
| static PyObject * |
| stopiteration_error(PyThreadState* tstate, PyObject *exc) |
| { |
| _PyInterpreterFrame *frame = tstate->cframe->current_frame; |
| assert(frame->owner == FRAME_OWNED_BY_GENERATOR); |
| assert(PyExceptionInstance_Check(exc)); |
| const char *msg = NULL; |
| if (PyErr_GivenExceptionMatches(exc, PyExc_StopIteration)) { |
| msg = "generator raised StopIteration"; |
| if (frame->f_code->co_flags & CO_ASYNC_GENERATOR) { |
| msg = "async generator raised StopIteration"; |
| } |
| else if (frame->f_code->co_flags & CO_COROUTINE) { |
| msg = "coroutine raised StopIteration"; |
| } |
| } |
| else if ((frame->f_code->co_flags & CO_ASYNC_GENERATOR) && |
| PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) |
| { |
| /* code in `gen` raised a StopAsyncIteration error: |
| raise a RuntimeError. |
| */ |
| msg = "async generator raised StopAsyncIteration"; |
| } |
| if (msg != NULL) { |
| PyObject *message = _PyUnicode_FromASCII(msg, strlen(msg)); |
| if (message == NULL) { |
| return NULL; |
| } |
| PyObject *error = PyObject_CallOneArg(PyExc_RuntimeError, message); |
| if (error == NULL) { |
| Py_DECREF(message); |
| return NULL; |
| } |
| assert(PyExceptionInstance_Check(error)); |
| PyException_SetCause(error, Py_NewRef(exc)); |
| // Steal exc reference, rather than Py_NewRef+Py_DECREF |
| PyException_SetContext(error, Py_NewRef(exc)); |
| Py_DECREF(message); |
| return error; |
| } |
| return Py_NewRef(exc); |
| } |
| |
| static PyObject * |
| unary_pos(PyThreadState* unused, PyObject *value) |
| { |
| return PyNumber_Positive(value); |
| } |
| |
| static PyObject * |
| list_to_tuple(PyThreadState* unused, PyObject *v) |
| { |
| assert(PyList_Check(v)); |
| return _PyTuple_FromArray(((PyListObject *)v)->ob_item, Py_SIZE(v)); |
| } |
| |
| instrinsic_func1 |
| _PyIntrinsics_UnaryFunctions[] = { |
| [0] = no_intrinsic, |
| [INTRINSIC_PRINT] = print_expr, |
| [INTRINSIC_IMPORT_STAR] = import_star, |
| [INTRINSIC_STOPITERATION_ERROR] = stopiteration_error, |
| [INTRINSIC_ASYNC_GEN_WRAP] = _PyAsyncGenValueWrapperNew, |
| [INTRINSIC_UNARY_POSITIVE] = unary_pos, |
| [INTRINSIC_LIST_TO_TUPLE] = list_to_tuple, |
| }; |