diff options
Diffstat (limited to 'Python/ceval.c')
| -rw-r--r-- | Python/ceval.c | 94 | 
1 files changed, 87 insertions, 7 deletions
| diff --git a/Python/ceval.c b/Python/ceval.c index 3758b09..9870a55 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 *, @@ -2322,7 +2322,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(); @@ -2362,26 +2362,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)) @@ -2441,7 +2448,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(); @@ -3383,6 +3390,64 @@ 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 = POP(); + +            /* 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 != NULL) { +                result = conv_fn(value); +                Py_DECREF(value); +                if (result == NULL) { +                    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 == NULL) { +                    goto error; +                } +            } + +            PUSH(result); +            DISPATCH(); +        } +          TARGET(EXTENDED_ARG) {              opcode = NEXTOP();              oparg = oparg<<16 | NEXTARG(); @@ -4261,7 +4326,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) @@ -4827,6 +4892,21 @@ update_star_args(int nstack, int nstar, PyObject *stararg,  {      PyObject *callargs, *w; +    if (!nstack) { +        if (!stararg) { +            /* There are no positional arguments on the stack and there is no +               sequence to be unpacked. */ +            return PyTuple_New(0); +        } +        if (PyTuple_CheckExact(stararg)) { +            /* No arguments are passed on the stack and the sequence is not a +               tuple subclass so we can just pass the stararg tuple directly +               to the function. */ +            Py_INCREF(stararg); +            return stararg; +        } +    } +      callargs = PyTuple_New(nstack + nstar);      if (callargs == NULL) {          return NULL; @@ -4915,7 +4995,7 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)      if (flags & CALL_FLAG_KW) {          kwdict = EXT_POP(*pp_stack); -        if (!PyDict_Check(kwdict)) { +        if (!PyDict_CheckExact(kwdict)) {              PyObject *d;              d = PyDict_New();              if (d == NULL) | 
