diff options
Diffstat (limited to 'Python/ceval.c')
| -rw-r--r-- | Python/ceval.c | 76 | 
1 files changed, 70 insertions, 6 deletions
| diff --git a/Python/ceval.c b/Python/ceval.c index 786adbf..3835cbb 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -125,7 +125,7 @@ static PyObject * load_args(PyObject ***, int);  #ifdef LLTRACE  static int lltrace; -static int prtrace(PyObject *, char *); +static int prtrace(PyObject *, const char *);  #endif  static int call_trace(Py_tracefunc, PyObject *,                        PyThreadState *, PyFrameObject *, @@ -2307,7 +2307,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              }              else {                  v = PyObject_GetItem(locals, name); -                if (v == NULL && _PyErr_OCCURRED()) { +                if (v == NULL) {                      if (!PyErr_ExceptionMatches(PyExc_KeyError))                          goto error;                      PyErr_Clear(); @@ -2347,26 +2347,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              PyObject *name = GETITEM(names, oparg);              PyObject *v;              if (PyDict_CheckExact(f->f_globals) -                && PyDict_CheckExact(f->f_builtins)) { +                && PyDict_CheckExact(f->f_builtins)) +            {                  v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,                                         (PyDictObject *)f->f_builtins,                                         name);                  if (v == NULL) { -                    if (!_PyErr_OCCURRED()) +                    if (!_PyErr_OCCURRED()) { +                        /* _PyDict_LoadGlobal() returns NULL without raising +                         * an exception if the key doesn't exist */                          format_exc_check_arg(PyExc_NameError,                                               NAME_ERROR_MSG, name); +                    }                      goto error;                  }                  Py_INCREF(v);              }              else {                  /* Slow-path if globals or builtins is not a dict */ + +                /* namespace 1: globals */                  v = PyObject_GetItem(f->f_globals, name);                  if (v == NULL) {                      if (!PyErr_ExceptionMatches(PyExc_KeyError))                          goto error;                      PyErr_Clear(); +                    /* namespace 2: builtins */                      v = PyObject_GetItem(f->f_builtins, name);                      if (v == NULL) {                          if (PyErr_ExceptionMatches(PyExc_KeyError)) @@ -2426,7 +2433,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              }              else {                  value = PyObject_GetItem(locals, name); -                if (value == NULL && PyErr_Occurred()) { +                if (value == NULL) {                      if (!PyErr_ExceptionMatches(PyExc_KeyError))                          goto error;                      PyErr_Clear(); @@ -3366,6 +3373,63 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              DISPATCH();          } +        TARGET(FORMAT_VALUE) { +            /* Handles f-string value formatting. */ +            PyObject *result; +            PyObject *fmt_spec; +            PyObject *value; +            PyObject *(*conv_fn)(PyObject *); +            int which_conversion = oparg & FVC_MASK; +            int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC; + +            fmt_spec = have_fmt_spec ? POP() : NULL; +            value = TOP(); + +            /* See if any conversion is specified. */ +            switch (which_conversion) { +            case FVC_STR:   conv_fn = PyObject_Str;   break; +            case FVC_REPR:  conv_fn = PyObject_Repr;  break; +            case FVC_ASCII: conv_fn = PyObject_ASCII; break; + +            /* Must be 0 (meaning no conversion), since only four +               values are allowed by (oparg & FVC_MASK). */ +            default:        conv_fn = NULL;           break; +            } + +            /* If there's a conversion function, call it and replace +               value with that result. Otherwise, just use value, +               without conversion. */ +            if (conv_fn) { +                result = conv_fn(value); +                Py_DECREF(value); +                if (!result) { +                    Py_XDECREF(fmt_spec); +                    goto error; +                } +                value = result; +            } + +            /* If value is a unicode object, and there's no fmt_spec, +               then we know the result of format(value) is value +               itself. In that case, skip calling format(). I plan to +               move this optimization in to PyObject_Format() +               itself. */ +            if (PyUnicode_CheckExact(value) && fmt_spec == NULL) { +                /* Do nothing, just transfer ownership to result. */ +                result = value; +            } else { +                /* Actually call format(). */ +                result = PyObject_Format(value, fmt_spec); +                Py_DECREF(value); +                Py_XDECREF(fmt_spec); +                if (!result) +                    goto error; +            } + +            SET_TOP(result); +            DISPATCH(); +        } +          TARGET(EXTENDED_ARG) {              opcode = NEXTOP();              oparg = oparg<<16 | NEXTARG(); @@ -4244,7 +4308,7 @@ Error:  #ifdef LLTRACE  static int -prtrace(PyObject *v, char *str) +prtrace(PyObject *v, const char *str)  {      printf("%s ", str);      if (PyObject_Print(v, stdout, 0) != 0) | 
