diff --git a/Doc/Makefile b/Doc/Makefile index 70ad703ac77e82..a090ee5ba92705 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -305,13 +305,15 @@ serve: # for development releases: always build .PHONY: autobuild-dev +autobuild-dev: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short) autobuild-dev: - $(MAKE) dist-no-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' + $(MAKE) dist-no-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION) # for HTML-only rebuilds .PHONY: autobuild-dev-html +autobuild-dev-html: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short) autobuild-dev-html: - $(MAKE) dist-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' + $(MAKE) dist-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION) # for stable releases: only build if not in pre-release stage (alpha, beta) # release candidate downloads are okay, since the stable tree can be in that stage diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index 6ae6bfe4aa6ab4..6eae24b38fae48 100644 --- a/Doc/c-api/code.rst +++ b/Doc/c-api/code.rst @@ -32,11 +32,13 @@ bound into a function. .. c:function:: Py_ssize_t PyCode_GetNumFree(PyCodeObject *co) - Return the number of free variables in a code object. + Return the number of :term:`free (closure) variables ` + in a code object. .. c:function:: int PyUnstable_Code_GetFirstFree(PyCodeObject *co) - Return the position of the first free variable in a code object. + Return the position of the first :term:`free (closure) variable ` + in a code object. .. versionchanged:: 3.13 @@ -144,7 +146,8 @@ bound into a function. Equivalent to the Python code ``getattr(co, 'co_freevars')``. Returns a new reference to a :c:type:`PyTupleObject` containing the names of - the free variables. On error, ``NULL`` is returned and an exception is raised. + the :term:`free (closure) variables `. On error, ``NULL`` is returned + and an exception is raised. .. versionadded:: 3.11 diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 561c8a1b879bae..8e0cf7bb0fc088 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -7,7 +7,8 @@ Initialization, Finalization, and Threads ***************************************** -See also the :ref:`Python Initialization Configuration `. +See :ref:`Python Initialization Configuration ` for details +on how to configure the interpreter prior to initialization. .. _pre-init-safe: @@ -21,6 +22,15 @@ a few functions and the :ref:`global configuration variables The following functions can be safely called before Python is initialized: +* Functions that initialize the interpreter: + + * :c:func:`Py_Initialize` + * :c:func:`Py_InitializeEx` + * :c:func:`Py_InitializeFromConfig` + * :c:func:`Py_BytesMain` + * :c:func:`Py_Main` + * the runtime pre-initialization functions covered in :ref:`init-config` + * Configuration functions: * :c:func:`PyImport_AppendInittab` @@ -32,6 +42,7 @@ The following functions can be safely called before Python is initialized: * :c:func:`Py_SetProgramName` * :c:func:`Py_SetPythonHome` * :c:func:`PySys_ResetWarnOptions` + * the configuration functions covered in :ref:`init-config` * Informative functions: @@ -43,10 +54,12 @@ The following functions can be safely called before Python is initialized: * :c:func:`Py_GetCopyright` * :c:func:`Py_GetPlatform` * :c:func:`Py_GetVersion` + * :c:func:`Py_IsInitialized` * Utilities: * :c:func:`Py_DecodeLocale` + * the status reporting and utility functions covered in :ref:`init-config` * Memory allocators: @@ -62,11 +75,13 @@ The following functions can be safely called before Python is initialized: .. note:: - The following functions **should not be called** before - :c:func:`Py_Initialize`: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, + Despite their apparent similarity to some of the functions listed above, + the following functions **should not be called** before the interpreter has + been initialized: :c:func:`Py_EncodeLocale`, :c:func:`Py_GetPath`, :c:func:`Py_GetPrefix`, :c:func:`Py_GetExecPrefix`, :c:func:`Py_GetProgramFullPath`, :c:func:`Py_GetPythonHome`, - :c:func:`Py_GetProgramName` and :c:func:`PyEval_InitThreads`. + :c:func:`Py_GetProgramName`, :c:func:`PyEval_InitThreads`, and + :c:func:`Py_RunMain`. .. _global-conf-vars: @@ -346,34 +361,42 @@ Initializing and finalizing the interpreter this should be called before using any other Python/C API functions; see :ref:`Before Python Initialization ` for the few exceptions. - This initializes - the table of loaded modules (``sys.modules``), and creates the fundamental - modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. It also initializes - the module search path (``sys.path``). It does not set ``sys.argv``; use - the new :c:type:`PyConfig` API of the :ref:`Python Initialization - Configuration ` for that. This is a no-op when called for a - second time - (without calling :c:func:`Py_FinalizeEx` first). There is no return value; it is a - fatal error if the initialization fails. - - Use the :c:func:`Py_InitializeFromConfig` function to customize the + This initializes the table of loaded modules (``sys.modules``), and creates + the fundamental modules :mod:`builtins`, :mod:`__main__` and :mod:`sys`. + It also initializes the module search path (``sys.path``). It does not set + ``sys.argv``; use the :ref:`Python Initialization Configuration ` + API for that. This is a no-op when called for a second time (without calling + :c:func:`Py_FinalizeEx` first). There is no return value; it is a fatal + error if the initialization fails. + + Use :c:func:`Py_InitializeFromConfig` to customize the :ref:`Python Initialization Configuration `. .. note:: - On Windows, changes the console mode from ``O_TEXT`` to ``O_BINARY``, which will - also affect non-Python uses of the console using the C Runtime. + On Windows, changes the console mode from ``O_TEXT`` to ``O_BINARY``, + which will also affect non-Python uses of the console using the C Runtime. .. c:function:: void Py_InitializeEx(int initsigs) This function works like :c:func:`Py_Initialize` if *initsigs* is ``1``. If - *initsigs* is ``0``, it skips initialization registration of signal handlers, which - might be useful when Python is embedded. + *initsigs* is ``0``, it skips initialization registration of signal handlers, + which may be useful when CPython is embedded as part of a larger application. - Use the :c:func:`Py_InitializeFromConfig` function to customize the + Use :c:func:`Py_InitializeFromConfig` to customize the :ref:`Python Initialization Configuration `. +.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config) + + Initialize Python from *config* configuration, as described in + :ref:`init-from-config`. + + See the :ref:`init-config` section for details on pre-initializing the + interpreter, populating the runtime configuration structure, and querying + the returned status structure. + + .. c:function:: int Py_IsInitialized() Return true (nonzero) when the Python interpreter has been initialized, false @@ -430,18 +453,121 @@ Initializing and finalizing the interpreter Some memory allocated by extension modules may not be freed. Some extensions may not work properly if their initialization routine is called more than once; this can happen if an application calls :c:func:`Py_Initialize` and :c:func:`Py_FinalizeEx` - more than once. + more than once. :c:func:`Py_FinalizeEx` must not be called recursively from + within itself. Therefore, it must not be called by any code that may be run + as part of the interpreter shutdown process, such as :py:mod:`atexit` + handlers, object finalizers, or any code that may be run while flushing the + stdout and stderr files. .. audit-event:: cpython._PySys_ClearAuditHooks "" c.Py_FinalizeEx .. versionadded:: 3.6 + .. c:function:: void Py_Finalize() This is a backwards-compatible version of :c:func:`Py_FinalizeEx` that disregards the return value. +.. c:function:: int Py_BytesMain(int argc, char **argv) + + Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings, + allowing the calling application to delegate the text decoding step to + the CPython runtime. + + .. versionadded:: 3.8 + + +.. c:function:: int Py_Main(int argc, wchar_t **argv) + + The main program for the standard interpreter, encapsulating a full + initialization/finalization cycle, as well as additional + behaviour to implement reading configurations settings from the environment + and command line, and then executing ``__main__`` in accordance with + :ref:`using-on-cmdline`. + + This is made available for programs which wish to support the full CPython + command line interface, rather than just embedding a Python runtime in a + larger application. + + The *argc* and *argv* parameters are similar to those which are passed to a + C program's :c:func:`main` function, except that the *argv* entries are first + converted to ``wchar_t`` using :c:func:`Py_DecodeLocale`. It is also + important to note that the argument list entries may be modified to point to + strings other than those passed in (however, the contents of the strings + pointed to by the argument list are not modified). + + The return value will be ``0`` if the interpreter exits normally (i.e., + without an exception), ``1`` if the interpreter exits due to an exception, + or ``2`` if the argument list does not represent a valid Python command + line. + + Note that if an otherwise unhandled :exc:`SystemExit` is raised, this + function will not return ``1``, but exit the process, as long as + ``Py_InspectFlag`` is not set. If ``Py_InspectFlag`` is set, execution will + drop into the interactive Python prompt, at which point a second otherwise + unhandled :exc:`SystemExit` will still exit the process, while any other + means of exiting will set the return value as described above. + + In terms of the CPython runtime configuration APIs documented in the + :ref:`runtime configuration ` section (and without accounting + for error handling), ``Py_Main`` is approximately equivalent to:: + + PyConfig config; + PyConfig_InitPythonConfig(&config); + PyConfig_SetArgv(&config, argc, argv); + Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + + Py_RunMain(); + + In normal usage, an embedding application will call this function + *instead* of calling :c:func:`Py_Initialize`, :c:func:`Py_InitializeEx` or + :c:func:`Py_InitializeFromConfig` directly, and all settings will be applied + as described elsewhere in this documentation. If this function is instead + called *after* a preceding runtime initialization API call, then exactly + which environmental and command line configuration settings will be updated + is version dependent (as it depends on which settings correctly support + being modified after they have already been set once when the runtime was + first initialized). + + +.. c:function:: int Py_RunMain(void) + + Executes the main module in a fully configured CPython runtime. + + Executes the command (:c:member:`PyConfig.run_command`), the script + (:c:member:`PyConfig.run_filename`) or the module + (:c:member:`PyConfig.run_module`) specified on the command line or in the + configuration. If none of these values are set, runs the interactive Python + prompt (REPL) using the ``__main__`` module's global namespace. + + If :c:member:`PyConfig.inspect` is not set (the default), the return value + will be ``0`` if the interpreter exits normally (that is, without raising + an exception), or ``1`` if the interpreter exits due to an exception. If an + otherwise unhandled :exc:`SystemExit` is raised, the function will immediately + exit the process instead of returning ``1``. + + If :c:member:`PyConfig.inspect` is set (such as when the :option:`-i` option + is used), rather than returning when the interpreter exits, execution will + instead resume in an interactive Python prompt (REPL) using the ``__main__`` + module's global namespace. If the interpreter exited with an exception, it + is immediately raised in the REPL session. The function return value is + then determined by the way the *REPL session* terminates: returning ``0`` + if the session terminates without raising an unhandled exception, exiting + immediately for an unhandled :exc:`SystemExit`, and returning ``1`` for + any other unhandled exception. + + This function always finalizes the Python interpreter regardless of whether + it returns a value or immediately exits the process due to an unhandled + :exc:`SystemExit` exception. + + See :ref:`Python Configuration ` for an example of a + customized Python that always runs in isolated mode using + :c:func:`Py_RunMain`. + + Process-wide parameters ======================= @@ -960,6 +1086,37 @@ thread, where the CPython global runtime was originally initialized. The only exception is if :c:func:`exec` will be called immediately after. +.. _cautions-regarding-runtime-finalization: + +Cautions regarding runtime finalization +--------------------------------------- + +In the late stage of :term:`interpreter shutdown`, after attempting to wait for +non-daemon threads to exit (though this can be interrupted by +:class:`KeyboardInterrupt`) and running the :mod:`atexit` functions, the runtime +is marked as *finalizing*: :c:func:`_Py_IsFinalizing` and +:func:`sys.is_finalizing` return true. At this point, only the *finalization +thread* that initiated finalization (typically the main thread) is allowed to +acquire the :term:`GIL`. + +If any thread, other than the finalization thread, attempts to acquire the GIL +during finalization, either explicitly via :c:func:`PyGILState_Ensure`, +:c:macro:`Py_END_ALLOW_THREADS`, :c:func:`PyEval_AcquireThread`, or +:c:func:`PyEval_AcquireLock`, or implicitly when the interpreter attempts to +reacquire it after having yielded it, the thread enters **a permanently blocked +state** where it remains until the program exits. In most cases this is +harmless, but this can result in deadlock if a later stage of finalization +attempts to acquire a lock owned by the blocked thread, or otherwise waits on +the blocked thread. + +Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++ +finalizations further up the call stack when such threads were forcibly exited +here in CPython 3.13 and earlier. The CPython runtime GIL acquiring C APIs +have never had any error reporting or handling expectations at GIL acquisition +time that would've allowed for graceful exit from this situation. Changing that +would require new stable C APIs and rewriting the majority of C code in the +CPython ecosystem to use those with error handling. + High-level API -------------- @@ -1033,11 +1190,14 @@ code, or when embedding the Python interpreter: ensues. .. note:: - Calling this function from a thread when the runtime is finalizing - will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to - check if the interpreter is in process of being finalized before calling - this function to avoid unwanted termination. + Calling this function from a thread when the runtime is finalizing will + hang the thread until the program exits, even if the thread was not + created by Python. Refer to + :ref:`cautions-regarding-runtime-finalization` for more details. + + .. versionchanged:: next + Hangs the current thread, rather than terminating it, if called while the + interpreter is finalizing. .. c:function:: PyThreadState* PyThreadState_Get() @@ -1092,11 +1252,14 @@ with sub-interpreters: to call arbitrary Python code. Failure is a fatal error. .. note:: - Calling this function from a thread when the runtime is finalizing - will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to - check if the interpreter is in process of being finalized before calling - this function to avoid unwanted termination. + Calling this function from a thread when the runtime is finalizing will + hang the thread until the program exits, even if the thread was not + created by Python. Refer to + :ref:`cautions-regarding-runtime-finalization` for more details. + + .. versionchanged:: next + Hangs the current thread, rather than terminating it, if called while the + interpreter is finalizing. .. c:function:: void PyGILState_Release(PyGILState_STATE) @@ -1224,7 +1387,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`. .. c:function:: void PyThreadState_DeleteCurrent(void) Destroy the current thread state and release the global interpreter lock. - Like :c:func:`PyThreadState_Delete`, the global interpreter lock need not + Like :c:func:`PyThreadState_Delete`, the global interpreter lock must be held. The thread state must have been reset with a previous call to :c:func:`PyThreadState_Clear`. @@ -1374,17 +1537,20 @@ All of the following functions must be called after :c:func:`Py_Initialize`. If this thread already has the lock, deadlock ensues. .. note:: - Calling this function from a thread when the runtime is finalizing - will terminate the thread, even if the thread was not created by Python. - You can use :c:func:`Py_IsFinalizing` or :func:`sys.is_finalizing` to - check if the interpreter is in process of being finalized before calling - this function to avoid unwanted termination. + Calling this function from a thread when the runtime is finalizing will + hang the thread until the program exits, even if the thread was not + created by Python. Refer to + :ref:`cautions-regarding-runtime-finalization` for more details. .. versionchanged:: 3.8 Updated to be consistent with :c:func:`PyEval_RestoreThread`, :c:func:`Py_END_ALLOW_THREADS`, and :c:func:`PyGILState_Ensure`, and terminate the current thread if called while the interpreter is finalizing. + .. versionchanged:: next + Hangs the current thread, rather than terminating it, if called while the + interpreter is finalizing. + :c:func:`PyEval_RestoreThread` is a higher-level function which is always available (even when threads have not been initialized). diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 9dc9ba61e7a60f..6f8962afc7af0d 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -1356,14 +1356,13 @@ the :option:`-X` command line option. The ``show_alloc_count`` field has been removed. +.. _init-from-config: + Initialization with PyConfig ---------------------------- -Function to initialize Python: - -.. c:function:: PyStatus Py_InitializeFromConfig(const PyConfig *config) - - Initialize Python from *config* configuration. +Initializing the interpreter from a populated configuration struct is handled +by calling :c:func:`Py_InitializeFromConfig`. The caller is responsible to handle exceptions (error or exit) using :c:func:`PyStatus_Exception` and :c:func:`Py_ExitStatusException`. @@ -1835,26 +1834,6 @@ return ``-1`` on error: } -Py_RunMain() -============ - -.. c:function:: int Py_RunMain(void) - - Execute the command (:c:member:`PyConfig.run_command`), the script - (:c:member:`PyConfig.run_filename`) or the module - (:c:member:`PyConfig.run_module`) specified on the command line or in the - configuration. - - By default and when if :option:`-i` option is used, run the REPL. - - Finally, finalizes Python and returns an exit status that can be passed to - the ``exit()`` function. - -See :ref:`Python Configuration ` for an example of -customized Python always running in isolated mode using -:c:func:`Py_RunMain`. - - Runtime Python configuration API ================================ diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst index 7a8a6134282ade..815afddad19df1 100644 --- a/Doc/c-api/tuple.rst +++ b/Doc/c-api/tuple.rst @@ -167,7 +167,8 @@ type. .. c:member:: const char *name - Name of the struct sequence type. + Fully qualified name of the type; null-terminated UTF-8 encoded. + The name must contain the module name. .. c:member:: const char *doc diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst index b2ac0c903c2bd7..f5704cffa199a5 100644 --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -1438,6 +1438,31 @@ They all return ``NULL`` or ``-1`` if an exception occurs. This function returns ``-1`` upon failure, so one should call :c:func:`PyErr_Occurred` to check for errors. + .. seealso:: + + The :c:func:`PyUnicode_Equal` function. + + +.. c:function:: int PyUnicode_Equal(PyObject *a, PyObject *b) + + Test if two strings are equal: + + * Return ``1`` if *a* is equal to *b*. + * Return ``0`` if *a* is not equal to *b*. + * Set a :exc:`TypeError` exception and return ``-1`` if *a* or *b* is not a + :class:`str` object. + + The function always succeeds if *a* and *b* are :class:`str` objects. + + The function works for :class:`str` subclasses, but does not honor custom + ``__eq__()`` method. + + .. seealso:: + + The :c:func:`PyUnicode_Compare` function. + + .. versionadded:: 3.14 + .. c:function:: int PyUnicode_EqualToUTF8AndSize(PyObject *unicode, const char *string, Py_ssize_t size) diff --git a/Doc/c-api/veryhigh.rst b/Doc/c-api/veryhigh.rst index 67167444d0a685..9f02bdb5896563 100644 --- a/Doc/c-api/veryhigh.rst +++ b/Doc/c-api/veryhigh.rst @@ -25,30 +25,6 @@ are only passed to these functions if it is certain that they were created by the same library that the Python runtime is using. -.. c:function:: int Py_Main(int argc, wchar_t **argv) - - The main program for the standard interpreter. This is made available for - programs which embed Python. The *argc* and *argv* parameters should be - prepared exactly as those which are passed to a C program's :c:func:`main` - function (converted to wchar_t according to the user's locale). It is - important to note that the argument list may be modified (but the contents of - the strings pointed to by the argument list are not). The return value will - be ``0`` if the interpreter exits normally (i.e., without an exception), - ``1`` if the interpreter exits due to an exception, or ``2`` if the parameter - list does not represent a valid Python command line. - - Note that if an otherwise unhandled :exc:`SystemExit` is raised, this - function will not return ``1``, but exit the process, as long as - :c:member:`PyConfig.inspect` is zero. - - -.. c:function:: int Py_BytesMain(int argc, char **argv) - - Similar to :c:func:`Py_Main` but *argv* is an array of bytes strings. - - .. versionadded:: 3.8 - - .. c:function:: int PyRun_AnyFile(FILE *fp, const char *filename) This is a simplified interface to :c:func:`PyRun_AnyFileExFlags` below, leaving diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat index 19dc71a345b474..9314facd2ad873 100644 --- a/Doc/data/stable_abi.dat +++ b/Doc/data/stable_abi.dat @@ -783,6 +783,7 @@ func,PyUnicode_DecodeUnicodeEscape,3.2,, func,PyUnicode_EncodeCodePage,3.7,on Windows, func,PyUnicode_EncodeFSDefault,3.2,, func,PyUnicode_EncodeLocale,3.7,, +func,PyUnicode_Equal,3.14,, func,PyUnicode_EqualToUTF8,3.13,, func,PyUnicode_EqualToUTF8AndSize,3.13,, func,PyUnicode_FSConverter,3.2,, diff --git a/Doc/glossary.rst b/Doc/glossary.rst index c9d3eba66b07d9..933fb0319452a6 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -231,6 +231,28 @@ Glossary A variable defined in a class and intended to be modified only at class level (i.e., not in an instance of the class). + closure variable + A :term:`free variable` referenced from a :term:`nested scope` that is defined in an outer + scope rather than being resolved at runtime from the globals or builtin namespaces. + May be explicitly defined with the :keyword:`nonlocal` keyword to allow write access, + or implicitly defined if the variable is only being read. + + For example, in the ``inner`` function in the following code, both ``x`` and ``print`` are + :term:`free variables `, but only ``x`` is a *closure variable*:: + + def outer(): + x = 0 + def inner(): + nonlocal x + x += 1 + print(x) + return inner + + Due to the :attr:`codeobject.co_freevars` attribute (which, despite its name, only + includes the names of closure variables rather than listing all referenced free + variables), the more general :term:`free variable` term is sometimes used even + when the intended meaning is to refer specifically to closure variables. + complex number An extension of the familiar real number system in which all numbers are expressed as a sum of a real part and an imaginary part. Imaginary @@ -454,6 +476,13 @@ Glossary the :term:`global interpreter lock` which allows only one thread to execute Python bytecode at a time. See :pep:`703`. + free variable + Formally, as defined in the :ref:`language execution model `, a free + variable is any variable used in a namespace which is not a local variable in that + namespace. See :term:`closure variable` for an example. + Pragmatically, due to the name of the :attr:`codeobject.co_freevars` attribute, + the term is also sometimes used as a synonym for :term:`closure variable`. + function A series of statements which returns some value to a caller. It can also be passed zero or more :term:`arguments ` which may be used in @@ -1160,16 +1189,12 @@ Glossary (subscript) notation uses :class:`slice` objects internally. soft deprecated - A soft deprecation can be used when using an API which should no longer - be used to write new code, but it remains safe to continue using it in - existing code. The API remains documented and tested, but will not be - developed further (no enhancement). - - The main difference between a "soft" and a (regular) "hard" deprecation - is that the soft deprecation does not imply scheduling the removal of the - deprecated API. + A soft deprecated API should not be used in new code, + but it is safe for already existing code to use it. + The API remains documented and tested, but will not be enhanced further. - Another difference is that a soft deprecation does not issue a warning. + Soft deprecation, unlike normal deprecation, does not plan on removing the API + and will not emit warnings. See `PEP 387: Soft Deprecation `_. diff --git a/Doc/howto/sockets.rst b/Doc/howto/sockets.rst index 0bbf97da39768d..cbc49d15a0771b 100644 --- a/Doc/howto/sockets.rst +++ b/Doc/howto/sockets.rst @@ -100,8 +100,8 @@ mainloop of the web server:: (clientsocket, address) = serversocket.accept() # now do something with the clientsocket # in this case, we'll pretend this is a threaded server - ct = client_thread(clientsocket) - ct.run() + ct = make_client_thread(clientsocket) + ct.start() There's actually 3 general ways in which this loop could work - dispatching a thread to handle ``clientsocket``, create a new process to handle diff --git a/Doc/library/_thread.rst b/Doc/library/_thread.rst index 81f0cac947f602..5fd604c05380ac 100644 --- a/Doc/library/_thread.rst +++ b/Doc/library/_thread.rst @@ -213,9 +213,8 @@ In addition to these methods, lock objects can also be used via the .. index:: pair: module; signal -* Threads interact strangely with interrupts: the :exc:`KeyboardInterrupt` - exception will be received by an arbitrary thread. (When the :mod:`signal` - module is available, interrupts always go to the main thread.) +* Interrupts always go to the main thread (the :exc:`KeyboardInterrupt` + exception will be received by that thread.) * Calling :func:`sys.exit` or raising the :exc:`SystemExit` exception is equivalent to calling :func:`_thread.exit`. @@ -229,7 +228,3 @@ In addition to these methods, lock objects can also be used via the :keyword:`try` ... :keyword:`finally` clauses or executing object destructors. -* When the main thread exits, it does not do any of its usual cleanup (except - that :keyword:`try` ... :keyword:`finally` clauses are honored), and the - standard I/O files are not flushed. - diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index a4683bccf651cd..83d0a9ed7b1d0a 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -30,7 +30,7 @@ Quick Links for ArgumentParser ========================= =========================================================================================================== ================================================================================== Name Description Values ========================= =========================================================================================================== ================================================================================== -prog_ The name of the program Defaults to ``os.path.basename(sys.argv[0])`` +prog_ The name of the program usage_ The string describing the program usage description_ A brief description of what the program does epilog_ Additional description of the program after the argument help @@ -214,8 +214,8 @@ ArgumentParser objects as keyword arguments. Each parameter has its own more detailed description below, but in short they are: - * prog_ - The name of the program (default: - ``os.path.basename(sys.argv[0])``) + * prog_ - The name of the program (default: generated from the ``__main__`` + module attributes and ``sys.argv[0]``) * usage_ - The string describing the program usage (default: generated from arguments added to parser) @@ -268,10 +268,18 @@ The following sections describe how each of these are used. prog ^^^^ -By default, :class:`ArgumentParser` objects use the base name -(see :func:`os.path.basename`) of ``sys.argv[0]`` to determine -how to display the name of the program in help messages. This default is almost -always desirable because it will make the help messages match the name that was +By default, :class:`ArgumentParser` calculates the name of the program +to display in help messages depending on the way the Python inerpreter was run: + +* The :func:`base name ` of ``sys.argv[0]`` if a file was + passed as argument. +* The Python interpreter name followed by ``sys.argv[0]`` if a directory or + a zipfile was passed as argument. +* The Python interpreter name followed by ``-m`` followed by the + module or package name if the :option:`-m` option was used. + +This default is almost +always desirable because it will make the help messages match the string that was used to invoke the program on the command line. For example, consider a file named ``myprogram.py`` with the following code:: @@ -281,7 +289,7 @@ named ``myprogram.py`` with the following code:: args = parser.parse_args() The help for this program will display ``myprogram.py`` as the program name -(regardless of where the program was invoked from): +(regardless of where the program was invoked from) if it is run as a script: .. code-block:: shell-session @@ -299,6 +307,17 @@ The help for this program will display ``myprogram.py`` as the program name -h, --help show this help message and exit --foo FOO foo help +If it is executed via the :option:`-m` option, the help will display a corresponding command line: + +.. code-block:: shell-session + + $ /usr/bin/python3 -m subdir.myprogram --help + usage: python3 -m subdir.myprogram [-h] [--foo FOO] + + options: + -h, --help show this help message and exit + --foo FOO foo help + To change this default behavior, another value can be supplied using the ``prog=`` argument to :class:`ArgumentParser`:: @@ -309,7 +328,8 @@ To change this default behavior, another value can be supplied using the options: -h, --help show this help message and exit -Note that the program name, whether determined from ``sys.argv[0]`` or from the +Note that the program name, whether determined from ``sys.argv[0]``, +from the ``__main__`` module attributes or from the ``prog=`` argument, is available to help messages using the ``%(prog)s`` format specifier. @@ -324,6 +344,9 @@ specifier. -h, --help show this help message and exit --foo FOO foo of the myprogram program +.. versionchanged:: 3.14 + The default ``prog`` value now reflects how ``__main__`` was actually executed, + rather than always being ``os.path.basename(sys.argv[0])``. usage ^^^^^ diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 535c5173be50de..d76b8d4809c078 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -2589,6 +2589,8 @@ fields, or any other data types containing pointer type fields. the structure when being packed or unpacked to/from memory. Setting this attribute to 0 is the same as not setting it at all. + .. versionadded:: 3.13 + .. attribute:: _layout_ An optional string naming the struct/union layout. It can currently diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 51c1a427b63787..e34b2db0210960 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -399,7 +399,7 @@ Module contents :func:`!astuple` raises :exc:`TypeError` if *obj* is not a dataclass instance. -.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False, module=None) +.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False, module=None, decorator=dataclass) Creates a new dataclass with name *cls_name*, fields as defined in *fields*, base classes as given in *bases*, and initialized @@ -415,6 +415,11 @@ Module contents of the dataclass is set to that value. By default, it is set to the module name of the caller. + The *decorator* parameter is a callable that will be used to create the dataclass. + It should take the class object as a first argument and the same keyword arguments + as :func:`@dataclass `. By default, the :func:`@dataclass ` + function is used. + This function is not strictly required, because any Python mechanism for creating a new class with :attr:`!__annotations__` can then apply the :func:`@dataclass ` function to convert that class to @@ -438,6 +443,9 @@ Module contents def add_one(self): return self.x + 1 + .. versionadded:: 3.14 + Added the *decorator* parameter. + .. function:: replace(obj, /, **changes) Creates a new object of the same type as *obj*, replacing diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index 59e2dbd6847538..64510a77c67c11 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -295,6 +295,20 @@ Instance attributes (read-only): Between 0 and 86,399 inclusive. + .. caution:: + + It is a somewhat common bug for code to unintentionally use this attribute + when it is actually intended to get a :meth:`~timedelta.total_seconds` + value instead: + + .. doctest:: + + >>> from datetime import timedelta + >>> duration = timedelta(seconds=11235813) + >>> duration.days, duration.seconds + (130, 3813) + >>> duration.total_seconds() + 11235813.0 .. attribute:: timedelta.microseconds @@ -351,7 +365,7 @@ Supported operations: | | same value. (2) | +--------------------------------+-----------------------------------------------+ | ``-t1`` | Equivalent to ``timedelta(-t1.days, | -| | -t1.seconds*, -t1.microseconds)``, | +| | -t1.seconds, -t1.microseconds)``, | | | and to ``t1 * -1``. (1)(4) | +--------------------------------+-----------------------------------------------+ | ``abs(t)`` | Equivalent to ``+t`` when ``t.days >= 0``, | diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index e3919c2ffad84c..1d084a8bf38d98 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -969,7 +969,8 @@ iterations of the loop. .. opcode:: GET_LEN - Perform ``STACK.append(len(STACK[-1]))``. + Perform ``STACK.append(len(STACK[-1]))``. Used in :keyword:`match` statements where + comparison with structure of pattern is needed. .. versionadded:: 3.10 @@ -1434,7 +1435,7 @@ iterations of the loop. slot ``i`` of the "fast locals" storage in this mapping. If the name is not found there, loads it from the cell contained in slot ``i``, similar to :opcode:`LOAD_DEREF`. This is used for loading - free variables in class bodies (which previously used + :term:`closure variables ` in class bodies (which previously used :opcode:`!LOAD_CLASSDEREF`) and in :ref:`annotation scopes ` within class bodies. @@ -1463,8 +1464,8 @@ iterations of the loop. .. opcode:: COPY_FREE_VARS (n) - Copies the ``n`` free variables from the closure into the frame. - Removes the need for special code on the caller's side when calling + Copies the ``n`` :term:`free (closure) variables ` from the closure + into the frame. Removes the need for special code on the caller's side when calling closures. .. versionadded:: 3.11 @@ -1937,10 +1938,10 @@ instructions: .. data:: hasfree - Sequence of bytecodes that access a free variable. 'free' in this - context refers to names in the current scope that are referenced by inner - scopes or names in outer scopes that are referenced from this scope. It does - *not* include references to global or builtin scopes. + Sequence of bytecodes that access a :term:`free (closure) variable `. + 'free' in this context refers to names in the current scope that are + referenced by inner scopes or names in outer scopes that are referenced + from this scope. It does *not* include references to global or builtin scopes. .. data:: hasname diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index a96f69e6170f00..7f8df704a33327 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -684,9 +684,10 @@ are always available. They are listed here in alphabetical order. ``__builtins__`` dictionary into *globals* before passing it to :func:`exec`. The *closure* argument specifies a closure--a tuple of cellvars. - It's only valid when the *object* is a code object containing free variables. - The length of the tuple must exactly match the number of free variables - referenced by the code object. + It's only valid when the *object* is a code object containing + :term:`free (closure) variables `. + The length of the tuple must exactly match the length of the code object'S + :attr:`~codeobject.co_freevars` attribute. .. audit-event:: exec code_object exec diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index 46136def06dc05..e26a2226aa947a 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -347,8 +347,7 @@ The :mod:`functools` module defines the following functions: def partial(func, /, *args, **keywords): def newfunc(*more_args, **more_keywords): - keywords_union = {**keywords, **more_keywords} - return func(*args, *more_args, **keywords_union) + return func(*args, *more_args, **(keywords | more_keywords)) newfunc.func = func newfunc.args = args newfunc.keywords = keywords diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst index 66ba621084c898..85d5a2d684d6eb 100644 --- a/Doc/library/importlib.metadata.rst +++ b/Doc/library/importlib.metadata.rst @@ -100,6 +100,13 @@ You can also get a :ref:`distribution's version number `, list its :ref:`requirements`. +.. exception:: PackageNotFoundError + + Subclass of :class:`ModuleNotFoundError` raised by several functions in this + module when queried for a distribution package which is not installed in the + current Python environment. + + Functional API ============== @@ -111,31 +118,53 @@ This package provides the following functionality via its public API. Entry points ------------ -The ``entry_points()`` function returns a collection of entry points. -Entry points are represented by ``EntryPoint`` instances; -each ``EntryPoint`` has a ``.name``, ``.group``, and ``.value`` attributes and -a ``.load()`` method to resolve the value. There are also ``.module``, -``.attr``, and ``.extras`` attributes for getting the components of the -``.value`` attribute. +.. function:: entry_points(**select_params) + + Returns a :class:`EntryPoints` instance describing entry points for the + current environment. Any given keyword parameters are passed to the + :meth:`!select` method for comparison to the attributes of + the individual entry point definitions. + + Note: it is not currently possible to query for entry points based on + their :attr:`!EntryPoint.dist` attribute (as different :class:`!Distribution` + instances do not currently compare equal, even if they have the same attributes) + +.. class:: EntryPoints + + Details of a collection of installed entry points. + + Also provides a ``.groups`` attribute that reports all identifed entry + point groups, and a ``.names`` attribute that reports all identified entry + point names. + +.. class:: EntryPoint + + Details of an installed entry point. + + Each :class:`!EntryPoint` instance has ``.name``, ``.group``, and ``.value`` + attributes and a ``.load()`` method to resolve the value. There are also + ``.module``, ``.attr``, and ``.extras`` attributes for getting the + components of the ``.value`` attribute, and ``.dist`` for obtaining + information regarding the distribution package that provides the entry point. Query all entry points:: >>> eps = entry_points() # doctest: +SKIP -The ``entry_points()`` function returns an ``EntryPoints`` object, -a collection of all ``EntryPoint`` objects with ``names`` and ``groups`` +The :func:`!entry_points` function returns a :class:`!EntryPoints` object, +a collection of all :class:`!EntryPoint` objects with ``names`` and ``groups`` attributes for convenience:: >>> sorted(eps.groups) # doctest: +SKIP ['console_scripts', 'distutils.commands', 'distutils.setup_keywords', 'egg_info.writers', 'setuptools.installation'] -``EntryPoints`` has a ``select`` method to select entry points +:class:`!EntryPoints` has a :meth:`!select` method to select entry points matching specific properties. Select entry points in the ``console_scripts`` group:: >>> scripts = eps.select(group='console_scripts') # doctest: +SKIP -Equivalently, since ``entry_points`` passes keyword arguments +Equivalently, since :func:`!entry_points` passes keyword arguments through to select:: >>> scripts = entry_points(group='console_scripts') # doctest: +SKIP @@ -189,31 +218,41 @@ for more information on entry points, their definition, and usage. Distribution metadata --------------------- -Every `Distribution Package `_ includes some metadata, -which you can extract using the -``metadata()`` function:: +.. function:: metadata(distribution_name) + + Return the distribution metadata corresponding to the named + distribution package as a :class:`PackageMetadata` instance. + + Raises :exc:`PackageNotFoundError` if the named distribution + package is not installed in the current Python environment. + +.. class:: PackageMetadata + + A concrete implementation of the + `PackageMetadata protocol `_. + + In addition to providing the defined protocol methods and attributes, subscripting + the instance is equivalent to calling the :meth:`!get` method. + +Every `Distribution Package `_ +includes some metadata, which you can extract using the :func:`!metadata` function:: >>> wheel_metadata = metadata('wheel') # doctest: +SKIP -The keys of the returned data structure, a ``PackageMetadata``, -name the metadata keywords, and +The keys of the returned data structure name the metadata keywords, and the values are returned unparsed from the distribution metadata:: >>> wheel_metadata['Requires-Python'] # doctest: +SKIP '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' -``PackageMetadata`` also presents a ``json`` attribute that returns +:class:`PackageMetadata` also presents a :attr:`!json` attribute that returns all the metadata in a JSON-compatible form per :PEP:`566`:: >>> wheel_metadata.json['requires_python'] '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' -.. note:: - - The actual type of the object returned by ``metadata()`` is an - implementation detail and should be accessed only through the interface - described by the - `PackageMetadata protocol `_. +The full set of available metadata is not described here. +See the PyPA `Core metadata specification `_ for additional details. .. versionchanged:: 3.10 The ``Description`` is now included in the metadata when presented @@ -227,7 +266,15 @@ all the metadata in a JSON-compatible form per :PEP:`566`:: Distribution versions --------------------- -The ``version()`` function is the quickest way to get a +.. function:: version(distribution_name) + + Return the installed distribution package version for the named + distribution package. + + Raises :exc:`PackageNotFoundError` if the named distribution + package is not installed in the current Python environment. + +The :func:`!version` function is the quickest way to get a `Distribution Package `_'s version number, as a string:: @@ -240,12 +287,28 @@ number, as a string:: Distribution files ------------------ -You can also get the full set of files contained within a distribution. The -``files()`` function takes a `Distribution Package `_ name -and returns all of the -files installed by this distribution. Each file object returned is a -``PackagePath``, a :class:`pathlib.PurePath` derived object with additional ``dist``, -``size``, and ``hash`` properties as indicated by the metadata. For example:: +.. function:: files(distribution_name) + + Return the full set of files contained within the named + distribution package. + + Raises :exc:`PackageNotFoundError` if the named distribution + package is not installed in the current Python environment. + + Returns :const:`None` if the distribution is found but the installation + database records reporting the files associated with the distribuion package + are missing. + +.. class:: PackagePath + + A :class:`pathlib.PurePath` derived object with additional ``dist``, + ``size``, and ``hash`` properties corresponding to the distribution + package's installation metadata for that file. + +The :func:`!files` function takes a +`Distribution Package `_ +name and returns all of the files installed by this distribution. Each file is reported +as a :class:`PackagePath` instance. For example:: >>> util = [p for p in files('wheel') if 'util.py' in str(p)][0] # doctest: +SKIP >>> util # doctest: +SKIP @@ -268,16 +331,16 @@ Once you have the file, you can also read its contents:: return s.encode('utf-8') return s -You can also use the ``locate`` method to get a the absolute path to the -file:: +You can also use the :meth:`!locate` method to get the absolute +path to the file:: >>> util.locate() # doctest: +SKIP PosixPath('/home/gustav/example/lib/site-packages/wheel/util.py') In the case where the metadata file listing files -(RECORD or SOURCES.txt) is missing, ``files()`` will -return ``None``. The caller may wish to wrap calls to -``files()`` in `always_iterable +(``RECORD`` or ``SOURCES.txt``) is missing, :func:`!files` will +return :const:`None`. The caller may wish to wrap calls to +:func:`!files` in `always_iterable `_ or otherwise guard against this condition if the target distribution is not known to have the metadata present. @@ -287,8 +350,16 @@ distribution is not known to have the metadata present. Distribution requirements ------------------------- +.. function:: requires(distribution_name) + + Return the declared dependency specifiers for the named + distribution package. + + Raises :exc:`PackageNotFoundError` if the named distribution + package is not installed in the current Python environment. + To get the full set of requirements for a `Distribution Package `_, -use the ``requires()`` +use the :func:`!requires` function:: >>> requires('wheel') # doctest: +SKIP @@ -301,6 +372,16 @@ function:: Mapping import to distribution packages --------------------------------------- +.. function:: packages_distributions() + + Return a mapping from the top level module and import package + names found via :attr:`sys.meta_path` to the names of the distribution + packages (if any) that provide the corresponding files. + + To allow for namespace packages (which may have members provided by + multiple distribution packages), each top level import name maps to a + list of distribution names rather than mapping directly to a single name. + A convenience method to resolve the `Distribution Package `_ name (or names, in the case of a namespace package) that provide each importable top-level @@ -320,23 +401,42 @@ function is not reliable with such installs. Distributions ============= -While the above API is the most common and convenient usage, you can get all -of that information from the ``Distribution`` class. A ``Distribution`` is an -abstract object that represents the metadata for -a Python `Distribution Package `_. You can -get the ``Distribution`` instance:: +.. function:: distribution(distribution_name) + + Return a :class:`Distribution` instance describing the named + distribution package. + + Raises :exc:`PackageNotFoundError` if the named distribution + package is not installed in the current Python environment. + +.. class:: Distribution + + Details of an installed distribution package. + + Note: different :class:`!Distribution` instances do not currently compare + equal, even if they relate to the same installed distribution and + accordingly have the same attributes. + +While the module level API described above is the most common and convenient usage, +you can get all of that information from the :class:`!Distribution` class. +:class:`!Distribution` is an abstract object that represents the metadata for +a Python `Distribution Package `_. +You can get the concreate :class:`!Distribution` subclass instance for an installed +distribution package by calling the :func:`distribution` function:: >>> from importlib.metadata import distribution # doctest: +SKIP >>> dist = distribution('wheel') # doctest: +SKIP + >>> type(dist) # doctest: +SKIP + Thus, an alternative way to get the version number is through the -``Distribution`` instance:: +:class:`!Distribution` instance:: >>> dist.version # doctest: +SKIP '0.32.3' -There are all kinds of additional metadata available on the ``Distribution`` -instance:: +There are all kinds of additional metadata available on :class:`!Distribution` +instances:: >>> dist.metadata['Requires-Python'] # doctest: +SKIP '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*' @@ -350,7 +450,7 @@ metadata:: 'file:///path/to/wheel-0.32.3.editable-py3-none-any.whl' The full set of available metadata is not described here. -See the `Core metadata specifications `_ for additional details. +See the PyPA `Core metadata specification `_ for additional details. .. versionadded:: 3.13 The ``.origin`` property was added. diff --git a/Doc/library/locale.rst b/Doc/library/locale.rst index 0246f99157024a..04035b33d0ed48 100644 --- a/Doc/library/locale.rst +++ b/Doc/library/locale.rst @@ -314,6 +314,15 @@ The :mod:`locale` module defines the following exception and functions: Get a representation of up to 100 values used to represent the values 0 to 99. + The function temporarily sets the ``LC_CTYPE`` locale to the locale + of the category that determines the requested value (``LC_TIME``, + ``LC_NUMERIC``, ``LC_MONETARY`` or ``LC_MESSAGES``) if locales are + different and the resulting string is non-ASCII. + This temporary change affects other threads. + + .. versionchanged:: 3.14 + The function now temporarily sets the ``LC_CTYPE`` locale in some cases. + .. function:: getdefaultlocale([envvars]) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 317ca8728248c8..0e9dc33ae2123a 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -753,16 +753,17 @@ The ``queue`` and ``listener`` keys are optional. If the ``queue`` key is present, the corresponding value can be one of the following: -* An object implementing the :class:`queue.Queue` public API. For instance, - this may be an actual instance of :class:`queue.Queue` or a subclass thereof, - or a proxy obtained by :meth:`multiprocessing.managers.SyncManager.Queue`. +* An object implementing the :meth:`Queue.put_nowait ` + and :meth:`Queue.get ` public API. For instance, this may be + an actual instance of :class:`queue.Queue` or a subclass thereof, or a proxy + obtained by :meth:`multiprocessing.managers.SyncManager.Queue`. This is of course only possible if you are constructing or modifying the configuration dictionary in code. * A string that resolves to a callable which, when called with no arguments, returns - the :class:`queue.Queue` instance to use. That callable could be a - :class:`queue.Queue` subclass or a function which returns a suitable queue instance, + the queue instance to use. That callable could be a :class:`queue.Queue` subclass + or a function which returns a suitable queue instance, such as ``my.module.queue_factory()``. * A dict with a ``'()'`` key which is constructed in the usual way as discussed in diff --git a/Doc/library/struct.rst b/Doc/library/struct.rst index 4769affdf1d666..3ea9e5ba071289 100644 --- a/Doc/library/struct.rst +++ b/Doc/library/struct.rst @@ -267,12 +267,26 @@ platform-dependent. | ``P`` | :c:expr:`void \*` | integer | | \(5) | +--------+--------------------------+--------------------+----------------+------------+ +Additionally, if IEC 60559 compatible complex arithmetic (Annex G of the +C11 standard) is supported, the following format characters are available: + ++--------+--------------------------+--------------------+----------------+------------+ +| Format | C Type | Python type | Standard size | Notes | ++========+==========================+====================+================+============+ +| ``E`` | :c:expr:`float complex` | complex | 8 | \(10) | ++--------+--------------------------+--------------------+----------------+------------+ +| ``C`` | :c:expr:`double complex` | complex | 16 | \(10) | ++--------+--------------------------+--------------------+----------------+------------+ + .. versionchanged:: 3.3 Added support for the ``'n'`` and ``'N'`` formats. .. versionchanged:: 3.6 Added support for the ``'e'`` format. +.. versionchanged:: 3.14 + Added support for the ``'E'`` and ``'C'`` formats. + Notes: @@ -349,6 +363,11 @@ Notes: of bytes. As a special case, ``'0s'`` means a single, empty string (while ``'0c'`` means 0 characters). +(10) + For the ``'E'`` and ``'C'`` format characters, the packed representation uses + the IEEE 754 binary32 and binary64 format for components of the complex + number, regardless of the floating-point format used by the platform. + A format character may be preceded by an integral repeat count. For example, the format string ``'4h'`` means exactly the same as ``'hhhh'``. diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst index 15e0b23aa12bf0..56cd6b8afaa73e 100644 --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -167,11 +167,12 @@ Examining Symbol Tables .. method:: get_nonlocals() - Return a tuple containing names of nonlocals in this function. + Return a tuple containing names of explicitly declared nonlocals in this function. .. method:: get_frees() - Return a tuple containing names of free variables in this function. + Return a tuple containing names of :term:`free (closure) variables ` + in this function. .. class:: Class diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index ac8bcceaca5aeb..f7140af2494898 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -50,16 +50,14 @@ Registering and using tools *tool_id* must be in the range 0 to 5 inclusive. Raises a :exc:`ValueError` if *tool_id* is in use. -.. function:: free_tool_id(tool_id: int, /) -> None +.. function:: clear_tool_id(tool_id: int, /) -> None - Should be called once a tool no longer requires *tool_id*. + Unregister all events and callback functions associated with *tool_id*. -.. note:: +.. function:: free_tool_id(tool_id: int, /) -> None - :func:`free_tool_id` will not disable global or local events associated - with *tool_id*, nor will it unregister any callback functions. This - function is only intended to be used to notify the VM that the - particular *tool_id* is no longer in use. + Should be called once a tool no longer requires *tool_id*. + Will call :func:`clear_tool_id` before releasing *tool_id*. .. function:: get_tool(tool_id: int, /) -> str | None diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 3c3c760c206ff2..84b80ec6efd59f 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -199,7 +199,7 @@ Standard names are defined for the following types: .. data:: CellType The type for cell objects: such objects are used as containers for - a function's free variables. + a function's :term:`closure variables `. .. versionadded:: 3.8 diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 513199d21456bf..d059a660548c7e 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -564,8 +564,9 @@ Special read-only attributes in which the function was defined. * - .. attribute:: function.__closure__ - - ``None`` or a :class:`tuple` of cells that contain bindings for the - function's free variables. + - ``None`` or a :class:`tuple` of cells that contain bindings for the names specified + in the :attr:`~codeobject.co_freevars` attribute of the function's + :attr:`code object `. A cell object has the attribute ``cell_contents``. This can be used to get the value of the cell, as well as set the value. @@ -1285,10 +1286,14 @@ Special read-only attributes * - .. attribute:: codeobject.co_cellvars - A :class:`tuple` containing the names of :ref:`local variables ` - that are referenced by nested functions inside the function + that are referenced from at least one :term:`nested scope` inside the function * - .. attribute:: codeobject.co_freevars - - A :class:`tuple` containing the names of free variables in the function + - A :class:`tuple` containing the names of + :term:`free (closure) variables ` that a :term:`nested scope` + references in an outer scope. See also :attr:`function.__closure__`. + + Note: references to global and builtin names are *not* included. * - .. attribute:: codeobject.co_code - A string representing the sequence of :term:`bytecode` instructions in diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst index 99cb09d09331d8..cb6c524dd97a30 100644 --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -90,7 +90,7 @@ If a name is bound in a block, it is a local variable of that block, unless declared as :keyword:`nonlocal` or :keyword:`global`. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not -defined there, it is a :dfn:`free variable`. +defined there, it is a :term:`free variable`. Each occurrence of a name in the program text refers to the :dfn:`binding` of that name established by the following name resolution rules. @@ -337,6 +337,9 @@ enclosing namespace, but in the global namespace. [#]_ The :func:`exec` and :func:`eval` functions have optional arguments to override the global and local namespace. If only one namespace is specified, it is used for both. +.. XXX(ncoghlan) above is only accurate for string execution. When executing code objects, + closure cells may now be passed explicitly to resolve co_freevars references. + Docs issue: https://github.com/python/cpython/issues/122826 .. _exceptions: diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index ab72ad49d041e1..decde0d297cf59 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1809,6 +1809,8 @@ returns a boolean value regardless of the type of its argument single: named expression pair: assignment; expression +.. _assignment-expressions: + Assignment expressions ====================== diff --git a/Doc/tools/extensions/patchlevel.py b/Doc/tools/extensions/patchlevel.py index 53ea1bf47b8fd3..9ccaec3dd5ce0f 100644 --- a/Doc/tools/extensions/patchlevel.py +++ b/Doc/tools/extensions/patchlevel.py @@ -74,4 +74,8 @@ def get_version_info(): if __name__ == "__main__": - print(format_version_info(get_header_version_info())[0]) + short_ver, full_ver = format_version_info(get_header_version_info()) + if sys.argv[1:2] == ["--short"]: + print(short_ver) + else: + print(full_ver) diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index c89b1693343b4e..b6623a2b8e01f1 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -353,8 +353,8 @@ def run(self): # Support for building "topic help" for pydoc pydoc_topic_labels = [ - 'assert', 'assignment', 'async', 'atom-identifiers', 'atom-literals', - 'attribute-access', 'attribute-references', 'augassign', 'await', + 'assert', 'assignment', 'assignment-expressions', 'async', 'atom-identifiers', + 'atom-literals', 'attribute-access', 'attribute-references', 'augassign', 'await', 'binary', 'bitwise', 'bltin-code-objects', 'bltin-ellipsis-object', 'bltin-null-object', 'bltin-type-objects', 'booleans', 'break', 'callable-types', 'calls', 'class', 'comparisons', 'compound', diff --git a/Doc/tutorial/introduction.rst b/Doc/tutorial/introduction.rst index 054bac59c955d5..65e3b1938bca9c 100644 --- a/Doc/tutorial/introduction.rst +++ b/Doc/tutorial/introduction.rst @@ -197,21 +197,19 @@ and workarounds. String literals can span multiple lines. One way is using triple-quotes: ``"""..."""`` or ``'''...'''``. End of lines are automatically included in the string, but it's possible to prevent this by adding a ``\`` at -the end of the line. The following example:: - - print("""\ +the end of the line. In the following example, the initial newline is not +included:: + + >>> print("""\ + ... Usage: thingy [OPTIONS] + ... -h Display this usage message + ... -H hostname Hostname to connect to + ... """) Usage: thingy [OPTIONS] -h Display this usage message -H hostname Hostname to connect to - """) - -produces the following output (note that the initial newline is not included): -.. code-block:: text - - Usage: thingy [OPTIONS] - -h Display this usage message - -H hostname Hostname to connect to + >>> Strings can be concatenated (glued together) with the ``+`` operator, and repeated with ``*``:: diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 136236f51eb511..20d872d7639219 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -23,8 +23,9 @@ available for application-local distributions. As specified in :pep:`11`, a Python release only supports a Windows platform while Microsoft considers the platform under extended support. This means that -Python |version| supports Windows 8.1 and newer. If you require Windows 7 -support, please install Python 3.8. +Python |version| supports Windows 10 and newer. If you require Windows 7 +support, please install Python 3.8. If you require Windows 8.1 support, +please install Python 3.12. There are a number of different installers available for Windows, each with certain benefits and downsides. diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst index ec110a3952c07c..fb8809feda4ec7 100644 --- a/Doc/whatsnew/3.12.rst +++ b/Doc/whatsnew/3.12.rst @@ -59,7 +59,7 @@ Summary -- Release highlights .. This section singles out the most important changes in Python 3.12. Brevity is key. -Python 3.12 is the latest stable release of the Python programming language, +Python 3.12 is a stable release of the Python programming language, with a mix of changes to the language and the standard library. The library changes focus on cleaning up deprecated APIs, usability, and correctness. Of note, the :mod:`!distutils` package has been removed from the standard library. diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 52fe749697cfa4..565f74149725d5 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -46,7 +46,7 @@ when researching a change. This article explains the new features in Python 3.13, compared to 3.12. -Python 3.13 will be released on October 1, 2024. +Python 3.13 was released on October 7, 2024. For full details, see the :ref:`changelog `. .. seealso:: @@ -60,7 +60,7 @@ Summary -- Release Highlights .. This section singles out the most important changes in Python 3.13. Brevity is key. -Python 3.13 will be the latest stable release of the Python programming +Python 3.13 is the latest stable release of the Python programming language, with a mix of changes to the language, the implementation and the standard library. The biggest changes include a new `interactive interpreter @@ -320,12 +320,9 @@ The free-threaded mode requires a different executable, usually called ``python3.13t`` or ``python3.13t.exe``. Pre-built binaries marked as *free-threaded* can be installed as part of the official :ref:`Windows ` -and :ref:`macOS ` installers, +and :ref:`macOS ` installers, or CPython can be built from source with the :option:`--disable-gil` option. -.. better macOS link pending - https://github.com/python/cpython/issues/109975#issuecomment-2286391179 - Free-threaded execution allows for full utilization of the available processing power by running threads in parallel on available CPU cores. While not all software will benefit from this automatically, programs @@ -501,30 +498,6 @@ are not tier 3 supported platforms, but will have best-effort support. .. seealso:: :pep:`730`, :pep:`738` -.. _whatsnew313-incremental-gc: - -Incremental garbage collection ------------------------------- - -The cycle garbage collector is now incremental. -This means that maximum pause times are reduced -by an order of magnitude or more for larger heaps. - -There are now only two generations: young and old. -When :func:`gc.collect` is not called directly, the -GC is invoked a little less frequently. When invoked, it -collects the young generation and an increment of the -old generation, instead of collecting one or more generations. - -The behavior of :func:`!gc.collect` changes slightly: - -* ``gc.collect(1)``: Performs an increment of garbage collection, - rather than collecting generation 1. -* Other calls to :func:`!gc.collect` are unchanged. - -(Contributed by Mark Shannon in :gh:`108362`.) - - Other Language Changes ====================== @@ -841,6 +814,10 @@ ctypes See :gh:`124520` for discussion and links to changes in some affected projects. +* :class:`ctypes.Structure` objects have a new :attr:`~ctypes.Structure._align_` + attribute which allows the alignment of the structure being packed to/from + memory to be specified explicitly. + (Contributed by Matt Sanderson in :gh:`112433`) dbm --- @@ -921,36 +898,6 @@ fractions (Contributed by Mark Dickinson in :gh:`111320`.) -gc --- - -The cyclic garbage collector is now incremental, -which changes the meaning of the results of -:meth:`~gc.get_threshold` and :meth:`~gc.set_threshold` -as well as :meth:`~gc.get_count` and :meth:`~gc.get_stats`. - -* For backwards compatibility, :meth:`~gc.get_threshold` continues to return - a three-item tuple. - The first value is the threshold for young collections, as before; - the second value determines the rate at which the old collection is scanned - (the default is 10, and higher values mean that the old collection - is scanned more slowly). - The third value is meaningless and is always zero. - -* :meth:`~gc.set_threshold` ignores any items after the second. - -* :meth:`~gc.get_count` and :meth:`~gc.get_stats` continue to return - the same format of results. - The only difference is that instead of the results referring to - the young, aging and old generations, - the results refer to the young generation - and the aging and collecting spaces of the old generation. - -In summary, code that attempted to manipulate the behavior of the cycle GC -may not work exactly as intended, but it is very unlikely to be harmful. -All other code will work just fine. - - glob ---- @@ -1515,11 +1462,6 @@ zipimport Optimizations ============= -* The new :ref:`incremental garbage collector ` - means that maximum pause times are reduced - by an order of magnitude or more for larger heaps. - (Contributed by Mark Shannon in :gh:`108362`.) - * Several standard library modules have had their import times significantly improved. For example, the import time of the :mod:`typing` module @@ -1621,7 +1563,7 @@ and are now removed: * :mod:`!msilib` * :mod:`!nis` * :mod:`!nntplib`: - Use the :pypi:`nntplib` library from PyPI instead. + Use the :pypi:`pynntp` library from PyPI instead. * :mod:`!ossaudiodev`: For audio playback, use the :pypi:`pygame` library from PyPI instead. * :mod:`!pipes`: @@ -2632,13 +2574,6 @@ Changes in the Python API Wrap it in :func:`staticmethod` if you want to preserve the old behavior. (Contributed by Serhiy Storchaka in :gh:`121027`.) -* The :ref:`garbage collector is now incremental `, - which means that the behavior of :func:`gc.collect` changes slightly: - - * ``gc.collect(1)``: Performs an increment of garbage collection, - rather than collecting generation 1. - * Other calls to :func:`!gc.collect` are unchanged. - * An :exc:`OSError` is now raised by :func:`getpass.getuser` for any failure to retrieve a username, instead of :exc:`ImportError` on non-Unix platforms diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index ffc001241ac5ec..4d71a24e9cc9ca 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -202,6 +202,13 @@ New Modules Improved Modules ================ +argparse +-------- + +* The default value of the :ref:`program name ` for + :class:`argparse.ArgumentParser` now reflects the way the Python + interpreter was instructed to find the ``__main__`` module code. + (Contributed by Serhiy Storchaka and Alyssa Coghlan in :gh:`66436`.) ast --- @@ -580,6 +587,12 @@ Changes in the Python API Wrap it in :func:`staticmethod` if you want to preserve the old behavior. (Contributed by Serhiy Storchaka and Dominykas Grigonis in :gh:`121027`.) +* The :func:`locale.nl_langinfo` function now sets temporarily the ``LC_CTYPE`` + locale in some cases. + This temporary change affects other threads. + (Contributed by Serhiy Storchaka in :gh:`69998`.) + + Build Changes ============= @@ -680,6 +693,10 @@ New Features `__ mentioned in :pep:`630` (:gh:`124153`). +* Add :c:func:`PyUnicode_Equal` function to the limited C API: + test if two strings are equal. + (Contributed by Victor Stinner in :gh:`124502`.) + Porting to Python 3.14 ---------------------- diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index d0e60bc280a217..fc9f49e65af847 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -428,9 +428,9 @@ Other Language Changes normal assignment syntax:: >>> def parse(family): - lastname, *members = family.split() - return lastname.upper(), *members - + ... lastname, *members = family.split() + ... return lastname.upper(), *members + ... >>> parse('simpsons homer marge bart lisa maggie') ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'maggie') diff --git a/Grammar/python.gram b/Grammar/python.gram index e9a8c69c4fa27c..b47028460b94f4 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -151,9 +151,9 @@ assignment[stmt_ty]: | a=('(' b=single_target ')' { b } | single_subscript_attribute_target) ':' b=expression c=['=' d=annotated_rhs { d }] { CHECK_VERSION(stmt_ty, 6, "Variable annotations syntax is", _PyAST_AnnAssign(a, b, c, 0, EXTRA)) } - | a[asdl_expr_seq*]=(z=star_targets '=' { z })+ b=(yield_expr | star_expressions) !'=' tc=[TYPE_COMMENT] { + | a[asdl_expr_seq*]=(z=star_targets '=' { z })+ b=annotated_rhs !'=' tc=[TYPE_COMMENT] { _PyAST_Assign(a, b, NEW_TYPE_COMMENT(p, tc), EXTRA) } - | a=single_target b=augassign ~ c=(yield_expr | star_expressions) { + | a=single_target b=augassign ~ c=annotated_rhs { _PyAST_AugAssign(a, b->kind, c, EXTRA) } | invalid_assignment diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 58d93fcfc1066b..03622698113ee7 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -8,6 +8,8 @@ extern "C" { #endif +/* Total tool ids available */ +#define _PY_MONITORING_TOOL_IDS 8 /* Count of all local monitoring events */ #define _PY_MONITORING_LOCAL_EVENTS 10 /* Count of all "real" monitoring events (not derived from other events) */ @@ -57,6 +59,8 @@ typedef struct { _Py_LocalMonitors active_monitors; /* The tools that are to be notified for events for the matching code unit */ uint8_t *tools; + /* The version of tools when they instrument the code */ + uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS]; /* Information to support line events */ _PyCoLineInstrumentationData *lines; /* The tools that are to be notified for line events for the matching code unit */ diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h index e2861c963266ea..b113c7fdcf6515 100644 --- a/Include/cpython/dictobject.h +++ b/Include/cpython/dictobject.h @@ -14,16 +14,11 @@ typedef struct { /* Number of items in the dictionary */ Py_ssize_t ma_used; - /* Dictionary version: globally unique, value change each time - the dictionary is modified */ -#ifdef Py_BUILD_CORE - /* Bits 0-7 are for dict watchers. + /* This is a private field for CPython's internal use. + * Bits 0-7 are for dict watchers. * Bits 8-11 are for the watched mutation counter (used by tier2 optimization) - * The remaining bits (12-63) are the actual version tag. */ - uint64_t ma_version_tag; -#else - Py_DEPRECATED(3.12) uint64_t ma_version_tag; -#endif + * The remaining bits are not currently used. */ + uint64_t _ma_watcher_tag; PyDictKeysObject *ma_keys; diff --git a/Include/cpython/longobject.h b/Include/cpython/longobject.h index b239f7c557e016..c1214d5e3714ea 100644 --- a/Include/cpython/longobject.h +++ b/Include/cpython/longobject.h @@ -2,6 +2,9 @@ # error "this header file must not be included directly" #endif +#define _PyLong_CAST(op) \ + (assert(PyLong_Check(op)), _Py_CAST(PyLongObject*, (op))) + PyAPI_FUNC(PyObject*) PyLong_FromUnicodeObject(PyObject *u, int base); #define Py_ASNATIVEBYTES_DEFAULTS -1 diff --git a/Include/cpython/weakrefobject.h b/Include/cpython/weakrefobject.h index 28acf7265a0856..9aa1a92c413fe9 100644 --- a/Include/cpython/weakrefobject.h +++ b/Include/cpython/weakrefobject.h @@ -42,13 +42,13 @@ struct _PyWeakReference { PyAPI_FUNC(void) _PyWeakref_ClearRef(PyWeakReference *self); +#define _PyWeakref_CAST(op) \ + (assert(PyWeakref_Check(op)), _Py_CAST(PyWeakReference*, (op))) + Py_DEPRECATED(3.13) static inline PyObject* PyWeakref_GET_OBJECT(PyObject *ref_obj) { - PyWeakReference *ref; - PyObject *obj; - assert(PyWeakref_Check(ref_obj)); - ref = _Py_CAST(PyWeakReference*, ref_obj); - obj = ref->wr_object; + PyWeakReference *ref = _PyWeakref_CAST(ref_obj); + PyObject *obj = ref->wr_object; // Explanation for the Py_REFCNT() check: when a weakref's target is part // of a long chain of deallocations which triggers the trashcan mechanism, // clearing the weakrefs can be delayed long after the target's refcount diff --git a/Include/internal/pycore_backoff.h b/Include/internal/pycore_backoff.h index a9d1bce127e63d..20436a68b69677 100644 --- a/Include/internal/pycore_backoff.h +++ b/Include/internal/pycore_backoff.h @@ -15,13 +15,7 @@ extern "C" { typedef struct { - union { - struct { - uint16_t backoff : 4; - uint16_t value : 12; - }; - uint16_t as_counter; // For printf("%#x", ...) - }; + uint16_t value_and_backoff; } _Py_BackoffCounter; @@ -38,17 +32,19 @@ typedef struct { and a 4-bit 'backoff' field. When resetting the counter, the backoff field is incremented (until it reaches a limit) and the value is set to a bit mask representing the value 2**backoff - 1. - The maximum backoff is 12 (the number of value bits). + The maximum backoff is 12 (the number of bits in the value). There is an exceptional value which must not be updated, 0xFFFF. */ -#define UNREACHABLE_BACKOFF 0xFFFF +#define BACKOFF_BITS 4 +#define MAX_BACKOFF 12 +#define UNREACHABLE_BACKOFF 15 static inline bool is_unreachable_backoff_counter(_Py_BackoffCounter counter) { - return counter.as_counter == UNREACHABLE_BACKOFF; + return counter.value_and_backoff == UNREACHABLE_BACKOFF; } static inline _Py_BackoffCounter @@ -57,8 +53,7 @@ make_backoff_counter(uint16_t value, uint16_t backoff) assert(backoff <= 15); assert(value <= 0xFFF); _Py_BackoffCounter result; - result.value = value; - result.backoff = backoff; + result.value_and_backoff = (value << BACKOFF_BITS) | backoff; return result; } @@ -66,7 +61,7 @@ static inline _Py_BackoffCounter forge_backoff_counter(uint16_t counter) { _Py_BackoffCounter result; - result.as_counter = counter; + result.value_and_backoff = counter; return result; } @@ -74,35 +69,36 @@ static inline _Py_BackoffCounter restart_backoff_counter(_Py_BackoffCounter counter) { assert(!is_unreachable_backoff_counter(counter)); - if (counter.backoff < 12) { - return make_backoff_counter((1 << (counter.backoff + 1)) - 1, counter.backoff + 1); + int backoff = counter.value_and_backoff & 15; + if (backoff < MAX_BACKOFF) { + return make_backoff_counter((1 << (backoff + 1)) - 1, backoff + 1); } else { - return make_backoff_counter((1 << 12) - 1, 12); + return make_backoff_counter((1 << MAX_BACKOFF) - 1, MAX_BACKOFF); } } static inline _Py_BackoffCounter pause_backoff_counter(_Py_BackoffCounter counter) { - return make_backoff_counter(counter.value | 1, counter.backoff); + _Py_BackoffCounter result; + result.value_and_backoff = counter.value_and_backoff | (1 << BACKOFF_BITS); + return result; } static inline _Py_BackoffCounter advance_backoff_counter(_Py_BackoffCounter counter) { - if (!is_unreachable_backoff_counter(counter)) { - return make_backoff_counter((counter.value - 1) & 0xFFF, counter.backoff); - } - else { - return counter; - } + _Py_BackoffCounter result; + result.value_and_backoff = counter.value_and_backoff - (1 << BACKOFF_BITS); + return result; } static inline bool backoff_counter_triggers(_Py_BackoffCounter counter) { - return counter.value == 0; + /* Test whether the value is zero and the backoff is not UNREACHABLE_BACKOFF */ + return counter.value_and_backoff < UNREACHABLE_BACKOFF; } /* Initial JUMP_BACKWARD counter. @@ -136,7 +132,7 @@ initial_temperature_backoff_counter(void) static inline _Py_BackoffCounter initial_unreachable_backoff_counter(void) { - return forge_backoff_counter(UNREACHABLE_BACKOFF); + return make_backoff_counter(0, UNREACHABLE_BACKOFF); } #ifdef __cplusplus diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 363845106e40dc..594fbb1c8e443b 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -251,6 +251,7 @@ typedef struct _special_method { } _Py_SpecialMethod; PyAPI_DATA(const _Py_SpecialMethod) _Py_SpecialMethods[]; +PyAPI_DATA(const size_t) _Py_FunctionAttributeOffsets[]; PyAPI_FUNC(int) _PyEval_CheckExceptStarTypeValid(PyThreadState *tstate, PyObject* right); PyAPI_FUNC(int) _PyEval_CheckExceptTypeValid(PyThreadState *tstate, PyObject* right); @@ -274,6 +275,8 @@ PyAPI_FUNC(PyObject *) _PyEval_GetANext(PyObject *aiter); PyAPI_FUNC(void) _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name, _PyStackRef *writeto); PyAPI_FUNC(PyObject *) _PyEval_GetAwaitable(PyObject *iterable, int oparg); PyAPI_FUNC(PyObject *) _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name); +PyAPI_FUNC(int) +_Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args); /* Bits that can be set in PyThreadState.eval_breaker */ #define _PY_GIL_DROP_REQUEST_BIT (1U << 0) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index f9a043b0208c8f..1920724c1d4f57 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -230,31 +230,6 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) { #define DICT_WATCHER_MASK ((1 << DICT_MAX_WATCHERS) - 1) #define DICT_WATCHER_AND_MODIFICATION_MASK ((1 << (DICT_MAX_WATCHERS + DICT_WATCHED_MUTATION_BITS)) - 1) -#ifdef Py_GIL_DISABLED - -#define THREAD_LOCAL_DICT_VERSION_COUNT 256 -#define THREAD_LOCAL_DICT_VERSION_BATCH THREAD_LOCAL_DICT_VERSION_COUNT * DICT_VERSION_INCREMENT - -static inline uint64_t -dict_next_version(PyInterpreterState *interp) -{ - PyThreadState *tstate = PyThreadState_GET(); - uint64_t cur_progress = (tstate->dict_global_version & - (THREAD_LOCAL_DICT_VERSION_BATCH - 1)); - if (cur_progress == 0) { - uint64_t next = _Py_atomic_add_uint64(&interp->dict_state.global_version, - THREAD_LOCAL_DICT_VERSION_BATCH); - tstate->dict_global_version = next; - } - return tstate->dict_global_version += DICT_VERSION_INCREMENT; -} - -#define DICT_NEXT_VERSION(INTERP) dict_next_version(INTERP) - -#else -#define DICT_NEXT_VERSION(INTERP) \ - ((INTERP)->dict_state.global_version += DICT_VERSION_INCREMENT) -#endif PyAPI_FUNC(void) _PyDict_SendEvent(int watcher_bits, @@ -263,7 +238,7 @@ _PyDict_SendEvent(int watcher_bits, PyObject *key, PyObject *value); -static inline uint64_t +static inline void _PyDict_NotifyEvent(PyInterpreterState *interp, PyDict_WatchEvent event, PyDictObject *mp, @@ -271,12 +246,11 @@ _PyDict_NotifyEvent(PyInterpreterState *interp, PyObject *value) { assert(Py_REFCNT((PyObject*)mp) > 0); - int watcher_bits = mp->ma_version_tag & DICT_WATCHER_MASK; + int watcher_bits = mp->_ma_watcher_tag & DICT_WATCHER_MASK; if (watcher_bits) { RARE_EVENT_STAT_INC(watched_dict_modification); _PyDict_SendEvent(watcher_bits, event, mp, key, value); } - return DICT_NEXT_VERSION(interp) | (mp->ma_version_tag & DICT_WATCHER_AND_MODIFICATION_MASK); } extern PyDictObject *_PyObject_MaterializeManagedDict(PyObject *obj); diff --git a/Include/internal/pycore_dict_state.h b/Include/internal/pycore_dict_state.h index 1a44755c7a01a3..11932b8d1e1ab6 100644 --- a/Include/internal/pycore_dict_state.h +++ b/Include/internal/pycore_dict_state.h @@ -12,10 +12,6 @@ extern "C" { #define DICT_WATCHED_MUTATION_BITS 4 struct _Py_dict_state { - /*Global counter used to set ma_version_tag field of dictionary. - * It is incremented each time that a dictionary is created and each - * time that a dictionary is modified. */ - uint64_t global_version; uint32_t next_keys_version; PyDict_WatchCallback watchers[DICT_MAX_WATCHERS]; }; diff --git a/Include/internal/pycore_function.h b/Include/internal/pycore_function.h index 6d44e933e8a8cb..c45d281125febb 100644 --- a/Include/internal/pycore_function.h +++ b/Include/internal/pycore_function.h @@ -18,6 +18,10 @@ extern PyObject* _PyFunction_Vectorcall( #define FUNC_MAX_WATCHERS 8 +#define FUNC_VERSION_UNSET 0 +#define FUNC_VERSION_CLEARED 1 +#define FUNC_VERSION_FIRST_VALID 2 + #define FUNC_VERSION_CACHE_SIZE (1<<12) /* Must be a power of 2 */ struct _func_version_cache_item { @@ -41,6 +45,12 @@ struct _py_func_state { extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr); +static inline int +_PyFunction_IsVersionValid(uint32_t version) +{ + return version >= FUNC_VERSION_FIRST_VALID; +} + extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func); PyAPI_FUNC(void) _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version); void _PyFunction_ClearCodeByVersion(uint32_t version); diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index 28a76c36801b4b..3140a75a47c5ee 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -757,6 +757,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_initializing)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_io)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_is_text_encoding)); + _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_isatty_open_only)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_length_)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_limbo)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_lock_unlock_module)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index ac789b06fb8a61..1591cb0a3f114f 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -246,6 +246,7 @@ struct _Py_global_strings { STRUCT_FOR_ID(_initializing) STRUCT_FOR_ID(_io) STRUCT_FOR_ID(_is_text_encoding) + STRUCT_FOR_ID(_isatty_open_only) STRUCT_FOR_ID(_length_) STRUCT_FOR_ID(_limbo) STRUCT_FOR_ID(_lock_unlock_module) diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index a1898d926ac39f..d7e584094f7839 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -35,7 +35,7 @@ extern "C" { #include "pycore_qsbr.h" // struct _qsbr_state #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_tuple.h" // struct _Py_tuple_state -#include "pycore_typeid.h" // struct _Py_type_id_pool +#include "pycore_uniqueid.h" // struct _Py_unique_id_pool #include "pycore_typeobject.h" // struct types_state #include "pycore_unicodeobject.h" // struct _Py_unicode_state #include "pycore_warnings.h" // struct _warnings_runtime_state @@ -221,7 +221,7 @@ struct _is { #if defined(Py_GIL_DISABLED) struct _mimalloc_interp_state mimalloc; struct _brc_state brc; // biased reference counting state - struct _Py_type_id_pool type_ids; + struct _Py_unique_id_pool unique_ids; // object ids for per-thread refcounts PyMutex weakref_locks[NUM_WEAKREF_LIST_LOCKS]; #endif @@ -272,6 +272,7 @@ struct _is { Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */ PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS]; PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS]; + uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS]; struct _Py_interp_cached_objects cached_objects; struct _Py_interp_static_objects static_objects; diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 2414d25d41bfbf..a88ff2deeba941 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -259,6 +259,7 @@ Known values: Python 3.14a1 3605 (Move ENTER_EXECUTOR to opcode 255) Python 3.14a1 3606 (Specialize CALL_KW) Python 3.14a1 3607 (Add pseudo instructions JUMP_IF_TRUE/FALSE) + Python 3.14a1 3608 (Add support for slices) Python 3.15 will start with 3650 @@ -271,7 +272,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3607 +#define PYC_MAGIC_NUMBER 3608 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_moduleobject.h b/Include/internal/pycore_moduleobject.h index 049677b292e235..cc2dda48ed9f28 100644 --- a/Include/internal/pycore_moduleobject.h +++ b/Include/internal/pycore_moduleobject.h @@ -46,7 +46,7 @@ static inline PyObject* _PyModule_GetDict(PyObject *mod) { } PyObject* _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress); -PyObject* _Py_module_getattro(PyModuleObject *m, PyObject *name); +PyObject* _Py_module_getattro(PyObject *m, PyObject *name); #ifdef __cplusplus } diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 80b588815bc9cf..0af13b1bcda20b 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -14,7 +14,7 @@ extern "C" { #include "pycore_interp.h" // PyInterpreterState.gc #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED #include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_typeid.h" // _PyType_IncrefSlow +#include "pycore_uniqueid.h" // _PyType_IncrefSlow #define _Py_IMMORTAL_REFCNT_LOOSE ((_Py_IMMORTAL_REFCNT >> 1) + 1) @@ -335,12 +335,12 @@ _Py_INCREF_TYPE(PyTypeObject *type) // Unsigned comparison so that `unique_id=-1`, which indicates that // per-thread refcounting has been disabled on this type, is handled by // the "else". - if ((size_t)ht->unique_id < (size_t)tstate->types.size) { + if ((size_t)ht->unique_id < (size_t)tstate->refcounts.size) { # ifdef Py_REF_DEBUG _Py_INCREF_IncRefTotal(); # endif _Py_INCREF_STAT_INC(); - tstate->types.refcounts[ht->unique_id]++; + tstate->refcounts.values[ht->unique_id]++; } else { // The slow path resizes the thread-local refcount array if necessary. @@ -368,12 +368,12 @@ _Py_DECREF_TYPE(PyTypeObject *type) // Unsigned comparison so that `unique_id=-1`, which indicates that // per-thread refcounting has been disabled on this type, is handled by // the "else". - if ((size_t)ht->unique_id < (size_t)tstate->types.size) { + if ((size_t)ht->unique_id < (size_t)tstate->refcounts.size) { # ifdef Py_REF_DEBUG _Py_DECREF_DecRefTotal(); # endif _Py_DECREF_STAT_INC(); - tstate->types.refcounts[ht->unique_id]--; + tstate->refcounts.values[ht->unique_id]--; } else { // Directly decref the type if the type id is not assigned or if diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 3344ede5e92c07..a0d3072d2cd5f6 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -483,8 +483,6 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 5; case YIELD_VALUE: return 1; - case _DO_CALL_FUNCTION_EX: - return 3 + (oparg & 1); default: return -1; } @@ -944,8 +942,6 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 6; case YIELD_VALUE: return 1; - case _DO_CALL_FUNCTION_EX: - return 1; default: return -1; } @@ -1022,7 +1018,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG }, [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, - [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG }, [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG }, [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG }, [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG }, @@ -1030,7 +1026,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_SUBSCR] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [BINARY_SUBSCR_DICT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [BINARY_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [BINARY_SUBSCR_GETITEM] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, [BINARY_SUBSCR_LIST_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, [BINARY_SUBSCR_STR_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, [BINARY_SUBSCR_TUPLE_INT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, @@ -1079,7 +1075,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [CONTAINS_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CONTAINS_OP_DICT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG }, + [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG }, [COPY_FREE_VARS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [DELETE_ATTR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1114,8 +1110,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [INSTRUMENTED_CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 }, [INSTRUMENTED_CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, - [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, + [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1127,10 +1123,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, + [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, 0 }, [IS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [JUMP_BACKWARD_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG }, @@ -1140,7 +1136,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_ATTR_CLASS] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_CLASS_WITH_METACLASS_CHECK] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG }, - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG }, [LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_METHOD_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG }, @@ -1148,7 +1144,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [LOAD_ATTR_MODULE] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, - [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [LOAD_ATTR_PROPERTY] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG }, [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1171,7 +1167,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MAKE_CELL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, - [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_KEYS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1192,13 +1188,13 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG }, [RETURN_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG }, - [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [RETURN_VALUE] = { true, INSTR_FMT_IX, 0 }, - [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, + [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [SET_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_EXIT_FLAG }, @@ -1218,10 +1214,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [TO_BOOL] = { true, INSTR_FMT_IXC00, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [TO_BOOL_ALWAYS_TRUE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, [TO_BOOL_BOOL] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, - [TO_BOOL_INT] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [TO_BOOL_INT] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, [TO_BOOL_LIST] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, [TO_BOOL_NONE] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, - [TO_BOOL_STR] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, + [TO_BOOL_STR] = { true, INSTR_FMT_IXC00, HAS_EXIT_FLAG }, [UNARY_INVERT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNARY_NEGATIVE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [UNARY_NOT] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, @@ -1231,8 +1227,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [UNPACK_SEQUENCE_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [UNPACK_SEQUENCE_TWO_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG }, - [_DO_CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, + [YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [JUMP] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [JUMP_IF_FALSE] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [JUMP_IF_TRUE] = { true, -1, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1661,7 +1656,6 @@ const char *_PyOpcode_OpName[266] = { [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", [WITH_EXCEPT_START] = "WITH_EXCEPT_START", [YIELD_VALUE] = "YIELD_VALUE", - [_DO_CALL_FUNCTION_EX] = "_DO_CALL_FUNCTION_EX", }; #endif @@ -1908,12 +1902,12 @@ const uint8_t _PyOpcode_Deopt[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = UNPACK_SEQUENCE, [WITH_EXCEPT_START] = WITH_EXCEPT_START, [YIELD_VALUE] = YIELD_VALUE, - [_DO_CALL_FUNCTION_EX] = _DO_CALL_FUNCTION_EX, }; #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ + case 116: \ case 117: \ case 118: \ case 119: \ diff --git a/Include/internal/pycore_pythread.h b/Include/internal/pycore_pythread.h index f3f5942444e851..a1e084cf67d58d 100644 --- a/Include/internal/pycore_pythread.h +++ b/Include/internal/pycore_pythread.h @@ -152,6 +152,19 @@ PyAPI_FUNC(int) PyThread_join_thread(PyThread_handle_t); * a non-zero value on failure. */ PyAPI_FUNC(int) PyThread_detach_thread(PyThread_handle_t); +/* + * Hangs the thread indefinitely without exiting it. + * + * gh-87135: There is no safe way to exit a thread other than returning + * normally from its start function. This is used during finalization in lieu + * of actually exiting the thread. Since the program is expected to terminate + * soon anyway, it does not matter if the thread stack stays around until then. + * + * This is unfortunate for embedders who may not be terminating their process + * when they're done with the interpreter, but our C API design does not allow + * for safely exiting threads attempting to re-enter Python post finalization. + */ +void _Py_NO_RETURN PyThread_hang_thread(void); #ifdef __cplusplus } diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index e6adb98eb19130..a17ba46966daa1 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -11,6 +11,7 @@ extern "C" { #include "pycore_ceval_state.h" // _PyEval_RUNTIME_PERF_INIT #include "pycore_faulthandler.h" // _faulthandler_runtime_state_INIT #include "pycore_floatobject.h" // _py_float_format_unknown +#include "pycore_function.h" #include "pycore_object.h" // _PyObject_HEAD_INIT #include "pycore_obmalloc_init.h" // _obmalloc_global_state_INIT #include "pycore_parser.h" // _parser_runtime_state_INIT @@ -243,7 +244,7 @@ extern PyTypeObject _PyExc_MemoryError; .dict_state = _dict_state_INIT, \ .mem_free_queue = _Py_mem_free_queue_INIT(INTERP.mem_free_queue), \ .func_state = { \ - .next_version = 1, \ + .next_version = FUNC_VERSION_FIRST_VALID, \ }, \ .types = { \ .next_version_tag = _Py_TYPE_BASE_VERSION_TAG, \ diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index 7847a5c63ebf3f..c9d20d0b5aacdb 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -755,6 +755,7 @@ extern "C" { INIT_ID(_initializing), \ INIT_ID(_io), \ INIT_ID(_is_text_encoding), \ + INIT_ID(_isatty_open_only), \ INIT_ID(_length_), \ INIT_ID(_limbo), \ INIT_ID(_lock_unlock_module), \ diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index b5b6993812057d..cf6dd22cfb18d1 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -111,7 +111,8 @@ PyStackRef_AsPyObjectBorrow(_PyStackRef stackref) static inline PyObject * PyStackRef_AsPyObjectSteal(_PyStackRef stackref) { - if (!PyStackRef_IsNull(stackref) && PyStackRef_IsDeferred(stackref)) { + assert(!PyStackRef_IsNull(stackref)); + if (PyStackRef_IsDeferred(stackref)) { return Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref)); } return PyStackRef_AsPyObjectBorrow(stackref); @@ -131,9 +132,10 @@ PyStackRef_AsPyObjectSteal(_PyStackRef stackref) static inline _PyStackRef _PyStackRef_FromPyObjectSteal(PyObject *obj) { + assert(obj != NULL); // Make sure we don't take an already tagged value. assert(((uintptr_t)obj & Py_TAG_BITS) == 0); - unsigned int tag = (obj == NULL || _Py_IsImmortal(obj)) ? (Py_TAG_DEFERRED) : Py_TAG_PTR; + unsigned int tag = _Py_IsImmortal(obj) ? (Py_TAG_DEFERRED) : Py_TAG_PTR; return ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag}); } # define PyStackRef_FromPyObjectSteal(obj) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj)) @@ -193,6 +195,7 @@ PyStackRef_FromPyObjectImmortal(PyObject *obj) # define PyStackRef_CLOSE(REF) \ do { \ _PyStackRef _close_tmp = (REF); \ + assert(!PyStackRef_IsNull(_close_tmp)); \ if (!PyStackRef_IsDeferred(_close_tmp)) { \ Py_DECREF(PyStackRef_AsPyObjectBorrow(_close_tmp)); \ } \ @@ -214,10 +217,11 @@ PyStackRef_FromPyObjectImmortal(PyObject *obj) static inline _PyStackRef PyStackRef_DUP(_PyStackRef stackref) { + assert(!PyStackRef_IsNull(stackref)); if (PyStackRef_IsDeferred(stackref)) { - assert(PyStackRef_IsNull(stackref) || - _Py_IsImmortal(PyStackRef_AsPyObjectBorrow(stackref)) || - _PyObject_HasDeferredRefcount(PyStackRef_AsPyObjectBorrow(stackref))); + assert(_Py_IsImmortal(PyStackRef_AsPyObjectBorrow(stackref)) || + _PyObject_HasDeferredRefcount(PyStackRef_AsPyObjectBorrow(stackref)) + ); return stackref; } Py_INCREF(PyStackRef_AsPyObjectBorrow(stackref)); diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index f681b644c9ad5d..a72ef4493b77ca 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -32,15 +32,15 @@ typedef struct _PyThreadStateImpl { struct _Py_freelists freelists; struct _brc_thread_state brc; struct { - // The thread-local refcounts for heap type objects - Py_ssize_t *refcounts; + // The per-thread refcounts + Py_ssize_t *values; // Size of the refcounts array. Py_ssize_t size; - // If set, don't use thread-local refcounts + // If set, don't use per-thread refcounts int is_finalized; - } types; + } refcounts; #endif #if defined(Py_REF_DEBUG) && defined(Py_GIL_DISABLED) diff --git a/Include/internal/pycore_typeid.h b/Include/internal/pycore_typeid.h deleted file mode 100644 index e64d1447f6b51d..00000000000000 --- a/Include/internal/pycore_typeid.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef Py_INTERNAL_TYPEID_H -#define Py_INTERNAL_TYPEID_H -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef Py_BUILD_CORE -# error "this header requires Py_BUILD_CORE define" -#endif - -#ifdef Py_GIL_DISABLED - -// This contains code for allocating unique ids to heap type objects -// and re-using those ids when the type is deallocated. -// -// The type ids are used to implement per-thread reference counts of -// heap type objects to avoid contention on the reference count fields -// of heap type objects. Static type objects are immortal, so contention -// is not an issue for those types. -// -// Type id of -1 is used to indicate a type doesn't use thread-local -// refcounting. This value is used when a type object is finalized by the GC -// and during interpreter shutdown to allow the type object to be -// deallocated promptly when the object's refcount reaches zero. -// -// Each entry implicitly represents a type id based on it's offset in the -// table. Non-allocated entries form a free-list via the 'next' pointer. -// Allocated entries store the corresponding PyTypeObject. -typedef union _Py_type_id_entry { - // Points to the next free type id, when part of the freelist - union _Py_type_id_entry *next; - - // Stores the type object when the id is assigned - PyHeapTypeObject *type; -} _Py_type_id_entry; - -struct _Py_type_id_pool { - PyMutex mutex; - - // combined table of types with allocated type ids and unallocated - // type ids. - _Py_type_id_entry *table; - - // Next entry to allocate inside 'table' or NULL - _Py_type_id_entry *freelist; - - // size of 'table' - Py_ssize_t size; -}; - -// Assigns the next id from the pool of type ids. -extern void _PyType_AssignId(PyHeapTypeObject *type); - -// Releases the allocated type id back to the pool. -extern void _PyType_ReleaseId(PyHeapTypeObject *type); - -// Merges the thread-local reference counts into the corresponding types. -extern void _PyType_MergeThreadLocalRefcounts(_PyThreadStateImpl *tstate); - -// Like _PyType_MergeThreadLocalRefcounts, but also frees the thread-local -// array of refcounts. -extern void _PyType_FinalizeThreadLocalRefcounts(_PyThreadStateImpl *tstate); - -// Frees the interpreter's pool of type ids. -extern void _PyType_FinalizeIdPool(PyInterpreterState *interp); - -// Increfs the type, resizing the thread-local refcount array if necessary. -PyAPI_FUNC(void) _PyType_IncrefSlow(PyHeapTypeObject *type); - -#endif /* Py_GIL_DISABLED */ - -#ifdef __cplusplus -} -#endif -#endif /* !Py_INTERNAL_TYPEID_H */ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index a688f70a2ba36f..d335373e88ee74 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -784,6 +784,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); + string = &_Py_ID(_isatty_open_only); + _PyUnicode_InternStatic(interp, &string); + assert(_PyUnicode_CheckConsistency(string, 1)); + assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(_length_); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Include/internal/pycore_uniqueid.h b/Include/internal/pycore_uniqueid.h new file mode 100644 index 00000000000000..8f3b4418408cf8 --- /dev/null +++ b/Include/internal/pycore_uniqueid.h @@ -0,0 +1,72 @@ +#ifndef Py_INTERNAL_UNIQUEID_H +#define Py_INTERNAL_UNIQUEID_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#ifdef Py_GIL_DISABLED + +// This contains code for allocating unique ids to objects for per-thread +// reference counting. +// +// Per-thread reference counting is used along with deferred reference +// counting to avoid scaling bottlenecks due to reference count contention. +// +// An id of -1 is used to indicate that an object doesn't use per-thread +// refcounting. This value is used when the object is finalized by the GC +// and during interpreter shutdown to allow the object to be +// deallocated promptly when the object's refcount reaches zero. +// +// Each entry implicitly represents a unique id based on its offset in the +// table. Non-allocated entries form a free-list via the 'next' pointer. +// Allocated entries store the corresponding PyObject. +typedef union _Py_unique_id_entry { + // Points to the next free type id, when part of the freelist + union _Py_unique_id_entry *next; + + // Stores the object when the id is assigned + PyObject *obj; +} _Py_unique_id_entry; + +struct _Py_unique_id_pool { + PyMutex mutex; + + // combined table of object with allocated unique ids and unallocated ids. + _Py_unique_id_entry *table; + + // Next entry to allocate inside 'table' or NULL + _Py_unique_id_entry *freelist; + + // size of 'table' + Py_ssize_t size; +}; + +// Assigns the next id from the pool of ids. +extern Py_ssize_t _PyObject_AssignUniqueId(PyObject *obj); + +// Releases the allocated id back to the pool. +extern void _PyObject_ReleaseUniqueId(Py_ssize_t unique_id); + +// Merges the per-thread reference counts into the corresponding objects. +extern void _PyObject_MergePerThreadRefcounts(_PyThreadStateImpl *tstate); + +// Like _PyObject_MergePerThreadRefcounts, but also frees the per-thread +// array of refcounts. +extern void _PyObject_FinalizePerThreadRefcounts(_PyThreadStateImpl *tstate); + +// Frees the interpreter's pool of type ids. +extern void _PyObject_FinalizeUniqueIdPool(PyInterpreterState *interp); + +// Increfs the type, resizing the per-thread refcount array if necessary. +PyAPI_FUNC(void) _PyType_IncrefSlow(PyHeapTypeObject *type); + +#endif /* Py_GIL_DISABLED */ + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_UNIQUEID_H */ diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 927dae88c1fa73..48bafacabcfd1d 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -97,54 +97,55 @@ extern "C" { #define _DICT_MERGE DICT_MERGE #define _DICT_UPDATE DICT_UPDATE #define _DO_CALL 356 -#define _DO_CALL_KW 357 -#define _DYNAMIC_EXIT 358 +#define _DO_CALL_FUNCTION_EX 357 +#define _DO_CALL_KW 358 +#define _DYNAMIC_EXIT 359 #define _END_SEND END_SEND -#define _ERROR_POP_N 359 +#define _ERROR_POP_N 360 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 360 -#define _EXPAND_METHOD_KW 361 -#define _FATAL_ERROR 362 +#define _EXPAND_METHOD 361 +#define _EXPAND_METHOD_KW 362 +#define _FATAL_ERROR 363 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 363 -#define _FOR_ITER_GEN_FRAME 364 -#define _FOR_ITER_TIER_TWO 365 +#define _FOR_ITER 364 +#define _FOR_ITER_GEN_FRAME 365 +#define _FOR_ITER_TIER_TWO 366 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE #define _GET_ITER GET_ITER #define _GET_LEN GET_LEN #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER -#define _GUARD_BOTH_FLOAT 366 -#define _GUARD_BOTH_INT 367 -#define _GUARD_BOTH_UNICODE 368 -#define _GUARD_BUILTINS_VERSION 369 -#define _GUARD_DORV_NO_DICT 370 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 371 -#define _GUARD_GLOBALS_VERSION 372 -#define _GUARD_IS_FALSE_POP 373 -#define _GUARD_IS_NONE_POP 374 -#define _GUARD_IS_NOT_NONE_POP 375 -#define _GUARD_IS_TRUE_POP 376 -#define _GUARD_KEYS_VERSION 377 -#define _GUARD_NOS_FLOAT 378 -#define _GUARD_NOS_INT 379 -#define _GUARD_NOT_EXHAUSTED_LIST 380 -#define _GUARD_NOT_EXHAUSTED_RANGE 381 -#define _GUARD_NOT_EXHAUSTED_TUPLE 382 -#define _GUARD_TOS_FLOAT 383 -#define _GUARD_TOS_INT 384 -#define _GUARD_TYPE_VERSION 385 +#define _GUARD_BOTH_FLOAT 367 +#define _GUARD_BOTH_INT 368 +#define _GUARD_BOTH_UNICODE 369 +#define _GUARD_BUILTINS_VERSION 370 +#define _GUARD_DORV_NO_DICT 371 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 372 +#define _GUARD_GLOBALS_VERSION 373 +#define _GUARD_IS_FALSE_POP 374 +#define _GUARD_IS_NONE_POP 375 +#define _GUARD_IS_NOT_NONE_POP 376 +#define _GUARD_IS_TRUE_POP 377 +#define _GUARD_KEYS_VERSION 378 +#define _GUARD_NOS_FLOAT 379 +#define _GUARD_NOS_INT 380 +#define _GUARD_NOT_EXHAUSTED_LIST 381 +#define _GUARD_NOT_EXHAUSTED_RANGE 382 +#define _GUARD_NOT_EXHAUSTED_TUPLE 383 +#define _GUARD_TOS_FLOAT 384 +#define _GUARD_TOS_INT 385 +#define _GUARD_TYPE_VERSION 386 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 386 -#define _INIT_CALL_PY_EXACT_ARGS 387 -#define _INIT_CALL_PY_EXACT_ARGS_0 388 -#define _INIT_CALL_PY_EXACT_ARGS_1 389 -#define _INIT_CALL_PY_EXACT_ARGS_2 390 -#define _INIT_CALL_PY_EXACT_ARGS_3 391 -#define _INIT_CALL_PY_EXACT_ARGS_4 392 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 387 +#define _INIT_CALL_PY_EXACT_ARGS 388 +#define _INIT_CALL_PY_EXACT_ARGS_0 389 +#define _INIT_CALL_PY_EXACT_ARGS_1 390 +#define _INIT_CALL_PY_EXACT_ARGS_2 391 +#define _INIT_CALL_PY_EXACT_ARGS_3 392 +#define _INIT_CALL_PY_EXACT_ARGS_4 393 #define _INSTRUMENTED_CALL_FUNCTION_EX INSTRUMENTED_CALL_FUNCTION_EX #define _INSTRUMENTED_CALL_KW INSTRUMENTED_CALL_KW #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER @@ -156,131 +157,133 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _INTERNAL_INCREMENT_OPT_COUNTER 393 -#define _IS_NONE 394 +#define _INTERNAL_INCREMENT_OPT_COUNTER 394 +#define _IS_NONE 395 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 395 -#define _ITER_CHECK_RANGE 396 -#define _ITER_CHECK_TUPLE 397 -#define _ITER_JUMP_LIST 398 -#define _ITER_JUMP_RANGE 399 -#define _ITER_JUMP_TUPLE 400 -#define _ITER_NEXT_LIST 401 -#define _ITER_NEXT_RANGE 402 -#define _ITER_NEXT_TUPLE 403 -#define _JUMP_TO_TOP 404 +#define _ITER_CHECK_LIST 396 +#define _ITER_CHECK_RANGE 397 +#define _ITER_CHECK_TUPLE 398 +#define _ITER_JUMP_LIST 399 +#define _ITER_JUMP_RANGE 400 +#define _ITER_JUMP_TUPLE 401 +#define _ITER_NEXT_LIST 402 +#define _ITER_NEXT_RANGE 403 +#define _ITER_NEXT_TUPLE 404 +#define _JUMP_TO_TOP 405 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 405 -#define _LOAD_ATTR_CLASS 406 -#define _LOAD_ATTR_CLASS_0 407 -#define _LOAD_ATTR_CLASS_1 408 +#define _LOAD_ATTR 406 +#define _LOAD_ATTR_CLASS 407 +#define _LOAD_ATTR_CLASS_0 408 +#define _LOAD_ATTR_CLASS_1 409 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 409 -#define _LOAD_ATTR_INSTANCE_VALUE_0 410 -#define _LOAD_ATTR_INSTANCE_VALUE_1 411 -#define _LOAD_ATTR_METHOD_LAZY_DICT 412 -#define _LOAD_ATTR_METHOD_NO_DICT 413 -#define _LOAD_ATTR_METHOD_WITH_VALUES 414 -#define _LOAD_ATTR_MODULE 415 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 416 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 417 -#define _LOAD_ATTR_PROPERTY_FRAME 418 -#define _LOAD_ATTR_SLOT 419 -#define _LOAD_ATTR_SLOT_0 420 -#define _LOAD_ATTR_SLOT_1 421 -#define _LOAD_ATTR_WITH_HINT 422 +#define _LOAD_ATTR_INSTANCE_VALUE 410 +#define _LOAD_ATTR_INSTANCE_VALUE_0 411 +#define _LOAD_ATTR_INSTANCE_VALUE_1 412 +#define _LOAD_ATTR_METHOD_LAZY_DICT 413 +#define _LOAD_ATTR_METHOD_NO_DICT 414 +#define _LOAD_ATTR_METHOD_WITH_VALUES 415 +#define _LOAD_ATTR_MODULE 416 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 417 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 418 +#define _LOAD_ATTR_PROPERTY_FRAME 419 +#define _LOAD_ATTR_SLOT 420 +#define _LOAD_ATTR_SLOT_0 421 +#define _LOAD_ATTR_SLOT_1 422 +#define _LOAD_ATTR_WITH_HINT 423 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 423 -#define _LOAD_CONST_INLINE_BORROW 424 -#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 425 -#define _LOAD_CONST_INLINE_WITH_NULL 426 +#define _LOAD_CONST_INLINE 424 +#define _LOAD_CONST_INLINE_BORROW 425 +#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 426 +#define _LOAD_CONST_INLINE_WITH_NULL 427 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 427 -#define _LOAD_FAST_0 428 -#define _LOAD_FAST_1 429 -#define _LOAD_FAST_2 430 -#define _LOAD_FAST_3 431 -#define _LOAD_FAST_4 432 -#define _LOAD_FAST_5 433 -#define _LOAD_FAST_6 434 -#define _LOAD_FAST_7 435 +#define _LOAD_FAST 428 +#define _LOAD_FAST_0 429 +#define _LOAD_FAST_1 430 +#define _LOAD_FAST_2 431 +#define _LOAD_FAST_3 432 +#define _LOAD_FAST_4 433 +#define _LOAD_FAST_5 434 +#define _LOAD_FAST_6 435 +#define _LOAD_FAST_7 436 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 436 -#define _LOAD_GLOBAL_BUILTINS 437 -#define _LOAD_GLOBAL_MODULE 438 +#define _LOAD_GLOBAL 437 +#define _LOAD_GLOBAL_BUILTINS 438 +#define _LOAD_GLOBAL_MODULE 439 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME #define _LOAD_SPECIAL LOAD_SPECIAL #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD +#define _MAKE_CALLARGS_A_TUPLE 440 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 439 +#define _MAKE_WARM 441 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE -#define _MAYBE_EXPAND_METHOD 440 -#define _MONITOR_CALL 441 -#define _MONITOR_JUMP_BACKWARD 442 -#define _MONITOR_RESUME 443 +#define _MAYBE_EXPAND_METHOD 442 +#define _MAYBE_EXPAND_METHOD_KW 443 +#define _MONITOR_CALL 444 +#define _MONITOR_JUMP_BACKWARD 445 +#define _MONITOR_RESUME 446 #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT -#define _POP_JUMP_IF_FALSE 444 -#define _POP_JUMP_IF_TRUE 445 +#define _POP_JUMP_IF_FALSE 447 +#define _POP_JUMP_IF_TRUE 448 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 446 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 449 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 447 +#define _PUSH_FRAME 450 #define _PUSH_NULL PUSH_NULL -#define _PY_FRAME_GENERAL 448 -#define _PY_FRAME_KW 449 -#define _QUICKEN_RESUME 450 -#define _REPLACE_WITH_TRUE 451 +#define _PY_FRAME_GENERAL 451 +#define _PY_FRAME_KW 452 +#define _QUICKEN_RESUME 453 +#define _REPLACE_WITH_TRUE 454 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 452 -#define _SEND 453 -#define _SEND_GEN_FRAME 454 +#define _SAVE_RETURN_OFFSET 455 +#define _SEND 456 +#define _SEND_GEN_FRAME 457 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SET_ADD SET_ADD #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_UPDATE SET_UPDATE -#define _START_EXECUTOR 455 -#define _STORE_ATTR 456 -#define _STORE_ATTR_INSTANCE_VALUE 457 -#define _STORE_ATTR_SLOT 458 -#define _STORE_ATTR_WITH_HINT 459 +#define _START_EXECUTOR 458 +#define _STORE_ATTR 459 +#define _STORE_ATTR_INSTANCE_VALUE 460 +#define _STORE_ATTR_SLOT 461 +#define _STORE_ATTR_WITH_HINT 462 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 460 -#define _STORE_FAST_0 461 -#define _STORE_FAST_1 462 -#define _STORE_FAST_2 463 -#define _STORE_FAST_3 464 -#define _STORE_FAST_4 465 -#define _STORE_FAST_5 466 -#define _STORE_FAST_6 467 -#define _STORE_FAST_7 468 +#define _STORE_FAST 463 +#define _STORE_FAST_0 464 +#define _STORE_FAST_1 465 +#define _STORE_FAST_2 466 +#define _STORE_FAST_3 467 +#define _STORE_FAST_4 468 +#define _STORE_FAST_5 469 +#define _STORE_FAST_6 470 +#define _STORE_FAST_7 471 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST #define _STORE_GLOBAL STORE_GLOBAL #define _STORE_NAME STORE_NAME -#define _STORE_SLICE 469 -#define _STORE_SUBSCR 470 +#define _STORE_SLICE 472 +#define _STORE_SUBSCR 473 #define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT #define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 471 -#define _TO_BOOL 472 +#define _TIER2_RESUME_CHECK 474 +#define _TO_BOOL 475 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT #define _TO_BOOL_LIST TO_BOOL_LIST @@ -290,14 +293,13 @@ extern "C" { #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 473 +#define _UNPACK_SEQUENCE 476 #define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST #define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE #define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define __DO_CALL_FUNCTION_EX _DO_CALL_FUNCTION_EX -#define MAX_UOP_ID 473 +#define MAX_UOP_ID 476 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 07606135d7a356..c68ee594947283 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -54,10 +54,10 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_UNARY_NOT] = HAS_PURE_FLAG, [_TO_BOOL] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_TO_BOOL_BOOL] = HAS_EXIT_FLAG, - [_TO_BOOL_INT] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_TO_BOOL_INT] = HAS_EXIT_FLAG, [_TO_BOOL_LIST] = HAS_EXIT_FLAG, [_TO_BOOL_NONE] = HAS_EXIT_FLAG, - [_TO_BOOL_STR] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG, + [_TO_BOOL_STR] = HAS_EXIT_FLAG, [_REPLACE_WITH_TRUE] = 0, [_UNARY_INVERT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GUARD_BOTH_INT] = HAS_EXIT_FLAG, @@ -74,7 +74,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_OP_SUBTRACT_FLOAT] = HAS_PURE_FLAG, [_GUARD_BOTH_UNICODE] = HAS_EXIT_FLAG, [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_PURE_FLAG, - [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG, [_BINARY_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_STORE_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -82,7 +82,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_BINARY_SUBSCR_STR_INT] = HAS_DEOPT_FLAG, [_BINARY_SUBSCR_TUPLE_INT] = HAS_DEOPT_FLAG, [_BINARY_SUBSCR_DICT] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_BINARY_SUBSCR_CHECK_FUNC] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_BINARY_SUBSCR_CHECK_FUNC] = HAS_DEOPT_FLAG, [_BINARY_SUBSCR_INIT_CALL] = 0, [_LIST_APPEND] = HAS_ARG_FLAG | HAS_ERROR_FLAG, [_SET_ADD] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -97,7 +97,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_GET_ANEXT] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_GET_AWAITABLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_SEND_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, - [_YIELD_VALUE] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_YIELD_VALUE] = HAS_ARG_FLAG, [_POP_EXCEPT] = HAS_ESCAPES_FLAG, [_LOAD_COMMON_CONSTANT] = HAS_ARG_FLAG, [_LOAD_BUILD_CLASS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -156,7 +156,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_LOAD_ATTR_CLASS_0] = 0, [_LOAD_ATTR_CLASS_1] = 0, [_LOAD_ATTR_CLASS] = HAS_ARG_FLAG | HAS_OPARG_AND_1_FLAG, - [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, + [_LOAD_ATTR_PROPERTY_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_GUARD_DORV_NO_DICT] = HAS_EXIT_FLAG, [_STORE_ATTR_INSTANCE_VALUE] = 0, [_STORE_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, @@ -225,7 +225,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CALL_TYPE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_CALL_STR_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, @@ -239,17 +239,19 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_METHOD_DESCRIPTOR_NOARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_METHOD_DESCRIPTOR_FAST] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MAYBE_EXPAND_METHOD_KW] = HAS_ARG_FLAG, [_PY_FRAME_KW] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CHECK_FUNCTION_VERSION_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CHECK_METHOD_VERSION_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_EXPAND_METHOD_KW] = HAS_ARG_FLAG, [_CHECK_IS_NOT_PY_CALLABLE_KW] = HAS_ARG_FLAG | HAS_EXIT_FLAG, [_CALL_KW_NON_PY] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, - [_RETURN_GENERATOR] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_CALLARGS_A_TUPLE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, + [_MAKE_FUNCTION] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_SET_FUNCTION_ATTRIBUTE] = HAS_ARG_FLAG, + [_RETURN_GENERATOR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_BUILD_SLICE] = HAS_ARG_FLAG | HAS_ERROR_FLAG, - [_CONVERT_VALUE] = HAS_ARG_FLAG | HAS_ERROR_FLAG, + [_CONVERT_VALUE] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_FORMAT_SIMPLE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_FORMAT_WITH_SPEC] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_COPY] = HAS_ARG_FLAG | HAS_PURE_FLAG, @@ -480,6 +482,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_LOAD_SPECIAL] = "_LOAD_SPECIAL", [_LOAD_SUPER_ATTR_ATTR] = "_LOAD_SUPER_ATTR_ATTR", [_LOAD_SUPER_ATTR_METHOD] = "_LOAD_SUPER_ATTR_METHOD", + [_MAKE_CALLARGS_A_TUPLE] = "_MAKE_CALLARGS_A_TUPLE", [_MAKE_CELL] = "_MAKE_CELL", [_MAKE_FUNCTION] = "_MAKE_FUNCTION", [_MAKE_WARM] = "_MAKE_WARM", @@ -489,6 +492,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_MATCH_MAPPING] = "_MATCH_MAPPING", [_MATCH_SEQUENCE] = "_MATCH_SEQUENCE", [_MAYBE_EXPAND_METHOD] = "_MAYBE_EXPAND_METHOD", + [_MAYBE_EXPAND_METHOD_KW] = "_MAYBE_EXPAND_METHOD_KW", [_NOP] = "_NOP", [_POP_EXCEPT] = "_POP_EXCEPT", [_POP_TOP] = "_POP_TOP", @@ -994,6 +998,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 2 + oparg; case _CALL_METHOD_DESCRIPTOR_FAST: return 2 + oparg; + case _MAYBE_EXPAND_METHOD_KW: + return 3 + oparg; case _PY_FRAME_KW: return 3 + oparg; case _CHECK_FUNCTION_VERSION_KW: @@ -1006,6 +1012,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 3 + oparg; case _CALL_KW_NON_PY: return 3 + oparg; + case _MAKE_CALLARGS_A_TUPLE: + return 3 + (oparg & 1); case _MAKE_FUNCTION: return 1; case _SET_FUNCTION_ATTRIBUTE: diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index 8ba1ab25a77770..327bdb792464a0 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -126,7 +126,6 @@ extern "C" { #define UNPACK_EX 113 #define UNPACK_SEQUENCE 114 #define YIELD_VALUE 115 -#define _DO_CALL_FUNCTION_EX 116 #define RESUME 149 #define BINARY_OP_ADD_FLOAT 150 #define BINARY_OP_ADD_INT 151 diff --git a/Include/pythread.h b/Include/pythread.h index a3216c51d66165..82247daf8e0aa0 100644 --- a/Include/pythread.h +++ b/Include/pythread.h @@ -17,7 +17,26 @@ typedef enum PyLockStatus { PyAPI_FUNC(void) PyThread_init_thread(void); PyAPI_FUNC(unsigned long) PyThread_start_new_thread(void (*)(void *), void *); -PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void); +/* Terminates the current thread. Considered unsafe. + * + * WARNING: This function is only safe to call if all functions in the full call + * stack are written to safely allow it. Additionally, the behavior is + * platform-dependent. This function should be avoided, and is no longer called + * by Python itself. It is retained only for compatibility with existing C + * extension code. + * + * With pthreads, calls `pthread_exit` causes some libcs (glibc?) to attempt to + * unwind the stack and call C++ destructors; if a `noexcept` function is + * reached, they may terminate the process. Others (macOS) do unwinding. + * + * On Windows, calls `_endthreadex` which kills the thread without calling C++ + * destructors. + * + * In either case there is a risk of invalid references remaining to data on the + * thread stack. + */ +Py_DEPRECATED(3.14) PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void); + PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void); #if (defined(__APPLE__) || defined(__linux__) || defined(_WIN32) \ diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h index dee00715b3c51d..2ce3a008b7129e 100644 --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -966,6 +966,10 @@ PyAPI_FUNC(int) PyUnicode_EqualToUTF8(PyObject *, const char *); PyAPI_FUNC(int) PyUnicode_EqualToUTF8AndSize(PyObject *, const char *, Py_ssize_t); #endif +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030e0000 +PyAPI_FUNC(int) PyUnicode_Equal(PyObject *str1, PyObject *str2); +#endif + /* Rich compare two strings and return one of the following: - NULL in case an exception was raised diff --git a/InternalDocs/compiler.md b/InternalDocs/compiler.md index ba31e16c3bbeaa..f27e73b274511f 100644 --- a/InternalDocs/compiler.md +++ b/InternalDocs/compiler.md @@ -324,14 +324,14 @@ basic block. As an example, consider the following code snippet: -.. code-block:: Python - - if x < 10: - f1() - f2() - else: - g() - end() +```python +if x < 10: + f1() + f2() +else: + g() +end() +``` The ``x < 10`` guard is represented by its own basic block that compares ``x`` with ``10`` and then ends in a conditional jump based on diff --git a/InternalDocs/exception_handling.md b/InternalDocs/exception_handling.md index ec09e0769929fa..64a346b55b8413 100644 --- a/InternalDocs/exception_handling.md +++ b/InternalDocs/exception_handling.md @@ -75,7 +75,8 @@ table. If it finds a handler, control flow transfers to it. Otherwise, the exception bubbles up to the caller, and the caller's frame is checked for a handler covering the `CALL` instruction. This repeats until a handler is found or the topmost frame is reached. -If no handler is found, the program terminates. During unwinding, +If no handler is found, then the interpreter function +(``_PyEval_EvalFrameDefault()``) returns NULL. During unwinding, the traceback is constructed as each frame is added to it by ``PyTraceBack_Here()``, which is in [Python/traceback.c](https://github.com/python/cpython/blob/main/Python/traceback.c). @@ -182,3 +183,13 @@ The interpreter's function to lookup the table by instruction offset is The Python function ``_parse_exception_table()`` in [Lib/dis.py](https://github.com/python/cpython/blob/main/Lib/dis.py) returns the exception table content as a list of namedtuple instances. + +Exception Chaining Implementation +--------------------------------- + +[Exception chaining](https://docs.python.org/dev/tutorial/errors.html#exception-chaining) +refers to setting the ``__context__`` and ``__cause__`` fields of an exception as it is +being raised. The ``__context__`` field is set by ``_PyErr_SetObject()`` in +[Python/errors.c](https://github.com/python/cpython/blob/main/Python/errors.c) +(which is ultimately called by all ``PyErr_Set*()`` functions). +The ``__cause__`` field (explicit chaining) is set by the ``RAISE_VARARGS`` bytecode. diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index dd70c5250c0b1e..9a793717cf082b 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -315,7 +315,6 @@ 'UNPACK_EX': 113, 'UNPACK_SEQUENCE': 114, 'YIELD_VALUE': 115, - '_DO_CALL_FUNCTION_EX': 116, 'INSTRUMENTED_END_FOR': 236, 'INSTRUMENTED_END_SEND': 237, 'INSTRUMENTED_LOAD_SUPER_ATTR': 238, diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 18849b309b8605..7b6d10c008d3cb 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -238,7 +238,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, result = raw try: line_buffering = False - if buffering == 1 or buffering < 0 and raw.isatty(): + if buffering == 1 or buffering < 0 and raw._isatty_open_only(): buffering = -1 line_buffering = True if buffering < 0: @@ -1794,6 +1794,21 @@ def isatty(self): self._checkClosed() return os.isatty(self._fd) + def _isatty_open_only(self): + """Checks whether the file is a TTY using an open-only optimization. + + TTYs are always character devices. If the interpreter knows a file is + not a character device when it would call ``isatty``, can skip that + call. Inside ``open()`` there is a fresh stat result that contains that + information. Use the stat result to skip a system call. Outside of that + context TOCTOU issues (the fd could be arbitrarily modified by + surrounding code). + """ + if (self._stat_atopen is not None + and not stat.S_ISCHR(self._stat_atopen.st_mode)): + return False + return os.isatty(self._fd) + @property def closefd(self): """True if the file descriptor will be closed by close().""" diff --git a/Lib/annotationlib.py b/Lib/annotationlib.py index a11188722487b2..d5166170c071c4 100644 --- a/Lib/annotationlib.py +++ b/Lib/annotationlib.py @@ -685,11 +685,9 @@ def get_annotations( case Format.FORWARDREF: # For FORWARDREF, we use __annotations__ if it exists try: - ann = _get_dunder_annotations(obj) + return dict(_get_dunder_annotations(obj)) except NameError: pass - else: - return dict(ann) # But if __annotations__ threw a NameError, we try calling __annotate__ ann = _get_and_call_annotate(obj, format) diff --git a/Lib/argparse.py b/Lib/argparse.py index 874f271959c4fe..21299b69ecd74c 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -527,8 +527,7 @@ def _format_action(self, action): def _format_action_invocation(self, action): if not action.option_strings: default = self._get_default_metavar_for_positional(action) - metavar, = self._metavar_formatter(action, default)(1) - return metavar + return ' '.join(self._metavar_formatter(action, default)(1)) else: @@ -703,7 +702,15 @@ def _get_action_name(argument): elif argument.option_strings: return '/'.join(argument.option_strings) elif argument.metavar not in (None, SUPPRESS): - return argument.metavar + metavar = argument.metavar + if not isinstance(metavar, tuple): + return metavar + if argument.nargs == ZERO_OR_MORE and len(metavar) == 2: + return '%s[, %s]' % metavar + elif argument.nargs == ONE_OR_MORE: + return '%s[, %s]' % metavar + else: + return ', '.join(metavar) elif argument.dest not in (None, SUPPRESS): return argument.dest elif argument.choices: @@ -1697,6 +1704,28 @@ def add_mutually_exclusive_group(self, *args, **kwargs): return super().add_mutually_exclusive_group(*args, **kwargs) +def _prog_name(prog=None): + if prog is not None: + return prog + arg0 = _sys.argv[0] + try: + modspec = _sys.modules['__main__'].__spec__ + except (KeyError, AttributeError): + # possibly PYTHONSTARTUP or -X presite or other weird edge case + # no good answer here, so fall back to the default + modspec = None + if modspec is None: + # simple script + return _os.path.basename(arg0) + py = _os.path.basename(_sys.executable) + if modspec.name != '__main__': + # imported module or package + modname = modspec.name.removesuffix('.__main__') + return f'{py} -m {modname}' + # directory or ZIP file + return f'{py} {arg0}' + + class ArgumentParser(_AttributeHolder, _ActionsContainer): """Object for parsing command line strings into Python objects. @@ -1740,11 +1769,7 @@ def __init__(self, argument_default=argument_default, conflict_handler=conflict_handler) - # default setting for prog - if prog is None: - prog = _os.path.basename(_sys.argv[0]) - - self.prog = prog + self.prog = _prog_name(prog) self.usage = usage self.epilog = epilog self.formatter_class = formatter_class diff --git a/Lib/asyncio/__main__.py b/Lib/asyncio/__main__.py index 5120140e061691..95c636f9e02866 100644 --- a/Lib/asyncio/__main__.py +++ b/Lib/asyncio/__main__.py @@ -1,6 +1,7 @@ import ast import asyncio import concurrent.futures +import contextvars import inspect import os import site @@ -22,6 +23,7 @@ def __init__(self, locals, loop): self.compile.compiler.flags |= ast.PyCF_ALLOW_TOP_LEVEL_AWAIT self.loop = loop + self.context = contextvars.copy_context() def runcode(self, code): global return_code @@ -55,12 +57,12 @@ def callback(): return try: - repl_future = self.loop.create_task(coro) + repl_future = self.loop.create_task(coro, context=self.context) futures._chain_future(repl_future, future) except BaseException as exc: future.set_exception(exc) - loop.call_soon_threadsafe(callback) + loop.call_soon_threadsafe(callback, context=self.context) try: return future.result() diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index ffcc0174e1e245..5dbe4b28d236d3 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -17,7 +17,6 @@ import collections.abc import concurrent.futures import errno -import functools import heapq import itertools import os @@ -1140,11 +1139,18 @@ async def create_connection( except OSError: continue else: # using happy eyeballs - sock, _, _ = await staggered.staggered_race( - (functools.partial(self._connect_sock, - exceptions, addrinfo, laddr_infos) - for addrinfo in infos), - happy_eyeballs_delay) + sock = (await staggered.staggered_race( + ( + # can't use functools.partial as it keeps a reference + # to exceptions + lambda addrinfo=addrinfo: self._connect_sock( + exceptions, addrinfo, laddr_infos + ) + for addrinfo in infos + ), + happy_eyeballs_delay, + loop=self, + ))[0] # can't use sock, _, _ as it keeks a reference to exceptions if sock is None: exceptions = [exc for sub in exceptions for exc in sub] diff --git a/Lib/asyncio/staggered.py b/Lib/asyncio/staggered.py index 6ccf5c3c269ff0..326c6f708944af 100644 --- a/Lib/asyncio/staggered.py +++ b/Lib/asyncio/staggered.py @@ -4,12 +4,11 @@ import contextlib +from . import events +from . import exceptions as exceptions_mod from . import locks from . import tasks -from . import taskgroups -class _Done(Exception): - pass async def staggered_race(coro_fns, delay, *, loop=None): """Run coroutines with staggered start times and take the first to finish. @@ -43,6 +42,8 @@ async def staggered_race(coro_fns, delay, *, loop=None): delay: amount of time, in seconds, between starting coroutines. If ``None``, the coroutines will run sequentially. + loop: the event loop to use. + Returns: tuple *(winner_result, winner_index, exceptions)* where @@ -61,11 +62,36 @@ async def staggered_race(coro_fns, delay, *, loop=None): """ # TODO: when we have aiter() and anext(), allow async iterables in coro_fns. + loop = loop or events.get_running_loop() + enum_coro_fns = enumerate(coro_fns) winner_result = None winner_index = None exceptions = [] + running_tasks = [] + + async def run_one_coro(previous_failed) -> None: + # Wait for the previous task to finish, or for delay seconds + if previous_failed is not None: + with contextlib.suppress(exceptions_mod.TimeoutError): + # Use asyncio.wait_for() instead of asyncio.wait() here, so + # that if we get cancelled at this point, Event.wait() is also + # cancelled, otherwise there will be a "Task destroyed but it is + # pending" later. + await tasks.wait_for(previous_failed.wait(), delay) + # Get the next coroutine to run + try: + this_index, coro_fn = next(enum_coro_fns) + except StopIteration: + return + # Start task that will run the next coroutine + this_failed = locks.Event() + next_task = loop.create_task(run_one_coro(this_failed)) + running_tasks.append(next_task) + assert len(running_tasks) == this_index + 2 + # Prepare place to put this coroutine's exceptions if not won + exceptions.append(None) + assert len(exceptions) == this_index + 1 - async def run_one_coro(this_index, coro_fn, this_failed): try: result = await coro_fn() except (SystemExit, KeyboardInterrupt): @@ -79,23 +105,35 @@ async def run_one_coro(this_index, coro_fn, this_failed): assert winner_index is None winner_index = this_index winner_result = result - raise _Done - + # Cancel all other tasks. We take care to not cancel the current + # task as well. If we do so, then since there is no `await` after + # here and CancelledError are usually thrown at one, we will + # encounter a curious corner case where the current task will end + # up as done() == True, cancelled() == False, exception() == + # asyncio.CancelledError. This behavior is specified in + # https://bugs.python.org/issue30048 + for i, t in enumerate(running_tasks): + if i != this_index: + t.cancel() + + first_task = loop.create_task(run_one_coro(None)) + running_tasks.append(first_task) try: - tg = taskgroups.TaskGroup() - # Intentionally override the loop in the TaskGroup to avoid - # using the running loop, preserving backwards compatibility - # TaskGroup only starts using `_loop` after `__aenter__` - # so overriding it here is safe. - tg._loop = loop - async with tg: - for this_index, coro_fn in enumerate(coro_fns): - this_failed = locks.Event() - exceptions.append(None) - tg.create_task(run_one_coro(this_index, coro_fn, this_failed)) - with contextlib.suppress(TimeoutError): - await tasks.wait_for(this_failed.wait(), delay) - except* _Done: - pass - - return winner_result, winner_index, exceptions + # Wait for a growing list of tasks to all finish: poor man's version of + # curio's TaskGroup or trio's nursery + done_count = 0 + while done_count != len(running_tasks): + done, _ = await tasks.wait(running_tasks) + done_count = len(done) + # If run_one_coro raises an unhandled exception, it's probably a + # programming error, and I want to see it. + if __debug__: + for d in done: + if d.done() and not d.cancelled() and d.exception(): + raise d.exception() + return winner_result, winner_index, exceptions + finally: + del exceptions + # Make sure no tasks are left running if we leave this function + for t in running_tasks: + t.cancel() diff --git a/Lib/bdb.py b/Lib/bdb.py index d7543017940d4f..666f9714eb9b7a 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -3,6 +3,7 @@ import fnmatch import sys import os +import weakref from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR __all__ = ["BdbQuit", "Bdb", "Breakpoint"] @@ -36,6 +37,7 @@ def __init__(self, skip=None): self.frame_returning = None self.trace_opcodes = False self.enterframe = None + self.code_linenos = weakref.WeakKeyDictionary() self._load_breaks() @@ -155,6 +157,9 @@ def dispatch_return(self, frame, arg): if self.stop_here(frame) or frame == self.returnframe: # Ignore return events in generator except when stepping. if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS: + # It's possible to trigger a StopIteration exception in + # the caller so we must set the trace function in the caller + self._set_caller_tracefunc(frame) return self.trace_dispatch try: self.frame_returning = frame @@ -273,9 +278,25 @@ def do_clear(self, arg): raise NotImplementedError("subclass of bdb must implement do_clear()") def break_anywhere(self, frame): - """Return True if there is any breakpoint for frame's filename. + """Return True if there is any breakpoint in that frame """ - return self.canonic(frame.f_code.co_filename) in self.breaks + filename = self.canonic(frame.f_code.co_filename) + if filename not in self.breaks: + return False + for lineno in self.breaks[filename]: + if self._lineno_in_frame(lineno, frame): + return True + return False + + def _lineno_in_frame(self, lineno, frame): + """Return True if the line number is in the frame's code object. + """ + code = frame.f_code + if lineno < code.co_firstlineno: + return False + if code not in self.code_linenos: + self.code_linenos[code] = set(lineno for _, _, lineno in code.co_lines()) + return lineno in self.code_linenos[code] # Derived classes should override the user_* methods # to gain control. @@ -360,7 +381,7 @@ def set_next(self, frame): def set_return(self, frame): """Stop when returning from the given frame.""" if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS: - self._set_stopinfo(frame, None, -1) + self._set_stopinfo(frame, frame, -1) else: self._set_stopinfo(frame.f_back, frame) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index cb3a61287bfe5d..4a368f02d851c5 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -208,8 +208,10 @@ class c_longdouble(_SimpleCData): try: class c_double_complex(_SimpleCData): _type_ = "C" + _check_size(c_double_complex) class c_float_complex(_SimpleCData): _type_ = "E" + _check_size(c_float_complex) class c_longdouble_complex(_SimpleCData): _type_ = "F" except AttributeError: diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index bdda7cc6c00f5d..7a24f8a9e5ccee 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1550,7 +1550,7 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, - weakref_slot=False, module=None): + weakref_slot=False, module=None, decorator=dataclass): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -1630,8 +1630,8 @@ def exec_body_callback(ns): if module is not None: cls.__module__ = module - # Apply the normal decorator. - return dataclass(cls, init=init, repr=repr, eq=eq, order=order, + # Apply the normal provided decorator. + return decorator(cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen, match_args=match_args, kw_only=kw_only, slots=slots, weakref_slot=weakref_slot) diff --git a/Lib/idlelib/tree.py b/Lib/idlelib/tree.py index 0726d7e23660f6..182ce7189614da 100644 --- a/Lib/idlelib/tree.py +++ b/Lib/idlelib/tree.py @@ -83,6 +83,8 @@ def wheel_event(event, widget=None): class TreeNode: + dy = 0 + def __init__(self, canvas, parent, item): self.canvas = canvas self.parent = parent @@ -199,23 +201,22 @@ def update(self): def draw(self, x, y): # XXX This hard-codes too many geometry constants! - dy = 20 self.x, self.y = x, y self.drawicon() self.drawtext() if self.state != 'expanded': - return y + dy + return y + TreeNode.dy # draw children if not self.children: sublist = self.item._GetSubList() if not sublist: # _IsExpandable() was mistaken; that's allowed - return y+17 + return y + TreeNode.dy for item in sublist: child = self.__class__(self.canvas, self, item) self.children.append(child) cx = x+20 - cy = y + dy + cy = y + TreeNode.dy cylast = 0 for child in self.children: cylast = cy @@ -289,6 +290,11 @@ def drawtext(self): self.label.bind("", lambda e: wheel_event(e, self.canvas)) self.label.bind("", lambda e: wheel_event(e, self.canvas)) self.text_id = id + if TreeNode.dy == 0: + # The first row doesn't matter what the dy is, just measure its + # size to get the value of the subsequent dy + coords = self.canvas.bbox(id) + TreeNode.dy = max(20, coords[3] - coords[1] - 3) def select_or_edit(self, event=None): if self.selected and self.item.IsEditable(): diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 3781cb1aeb9ae2..6a6a7f726f7e0c 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -499,7 +499,7 @@ def as_tuple(self, value): def _is_queue_like_object(obj): """Check that *obj* implements the Queue API.""" - if isinstance(obj, queue.Queue): + if isinstance(obj, (queue.Queue, queue.SimpleQueue)): return True # defer importing multiprocessing as much as possible from multiprocessing.queues import Queue as MPQueue @@ -516,13 +516,13 @@ def _is_queue_like_object(obj): # Ideally, we would have wanted to simply use strict type checking # instead of a protocol-based type checking since the latter does # not check the method signatures. - queue_interface = [ - 'empty', 'full', 'get', 'get_nowait', - 'put', 'put_nowait', 'join', 'qsize', - 'task_done', - ] + # + # Note that only 'put_nowait' and 'get' are required by the logging + # queue handler and queue listener (see gh-124653) and that other + # methods are either optional or unused. + minimal_queue_interface = ['put_nowait', 'get'] return all(callable(getattr(obj, method, None)) - for method in queue_interface) + for method in minimal_queue_interface) class DictConfigurator(BaseConfigurator): """ diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 97bb4eb52f4386..ae56c136608472 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -417,33 +417,43 @@ 'caused a\n' 'syntax error.\n', 'assignment-expressions': 'Assignment expressions\n' - '**********************\n' - '\n' - 'An assignment expression (sometimes also called a “named expression”' - '\nor “walrus”) assigns an expression to an identifier, while also\n' - 'returning the value of the expression.\n' - '\n' - 'One common use case is when handling matched regular expressions:\n' - '\n' - ' if matching := pattern.search(data):\n' - ' do_something(matching)\n' - '\n' - 'Or, when processing a file stream in chunks:\n' - '\n' - ' while chunk := file.read(9000):\n' - ' process(chunk)\n' - '\n' - 'Assignment expressions must be surrounded by parentheses when used as\n' - 'expression statements and when used as sub-expressions in slicing,\n' - 'conditional, lambda, keyword-argument, and comprehension-if\n' - 'expressions and in assert, with, and assignment statements. In all\n' - 'other places where they can be used, parentheses are not required,\n' - 'including in if and while statements.\n' - '\n' - 'Added in version 3.8.\n' - 'See also:\n' - '\n' - ' **PEP 572** - Assignment Expressions\n', + '**********************\n' + '\n' + ' assignment_expression ::= [identifier ":="] ' + 'expression\n' + '\n' + 'An assignment expression (sometimes also called a ' + '“named expression”\n' + 'or “walrus”) assigns an "expression" to an ' + '"identifier", while also\n' + 'returning the value of the "expression".\n' + '\n' + 'One common use case is when handling matched ' + 'regular expressions:\n' + '\n' + ' if matching := pattern.search(data):\n' + ' do_something(matching)\n' + '\n' + 'Or, when processing a file stream in chunks:\n' + '\n' + ' while chunk := file.read(9000):\n' + ' process(chunk)\n' + '\n' + 'Assignment expressions must be surrounded by ' + 'parentheses when used as\n' + 'expression statements and when used as ' + 'sub-expressions in slicing,\n' + 'conditional, lambda, keyword-argument, and ' + 'comprehension-if\n' + 'expressions and in "assert", "with", and ' + '"assignment" statements. In\n' + 'all other places where they can be used, ' + 'parentheses are not required,\n' + 'including in "if" and "while" statements.\n' + '\n' + 'Added in version 3.8: See **PEP 572** for more ' + 'details about\n' + 'assignment expressions.\n', 'async': 'Coroutines\n' '**********\n' '\n' diff --git a/Lib/shutil.py b/Lib/shutil.py index dab3ca5ee91245..dd3e0e0c5da54b 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -44,7 +44,7 @@ else: _winapi = None -COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 64 * 1024 +COPY_BUFSIZE = 1024 * 1024 if _WINDOWS else 256 * 1024 # This should never be removed, see rationale in: # https://bugs.python.org/issue43743#msg393429 _USE_CP_SENDFILE = (hasattr(os, "sendfile") diff --git a/Lib/site.py b/Lib/site.py index cafd3ab70b2cac..b3194d79fb5ab8 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -491,12 +491,21 @@ def register_readline(): This can be overridden in the sitecustomize or usercustomize module, or in a PYTHONSTARTUP file. """ + if not sys.flags.ignore_environment: + PYTHON_BASIC_REPL = os.getenv("PYTHON_BASIC_REPL") + else: + PYTHON_BASIC_REPL = False + import atexit try: import readline import rlcompleter # noqa: F401 - import _pyrepl.readline - import _pyrepl.unix_console + if PYTHON_BASIC_REPL: + CAN_USE_PYREPL = False + else: + import _pyrepl.readline + import _pyrepl.unix_console + from _pyrepl.main import CAN_USE_PYREPL except ImportError: return @@ -517,7 +526,6 @@ def register_readline(): pass if readline.get_current_history_length() == 0: - from _pyrepl.main import CAN_USE_PYREPL # If no history was loaded, default to .python_history, # or PYTHON_HISTORY. # The guard is necessary to avoid doubling history size at @@ -525,13 +533,17 @@ def register_readline(): # through a PYTHONSTARTUP hook, see: # http://bugs.python.org/issue5845#msg198636 history = gethistoryfile() - if os.getenv("PYTHON_BASIC_REPL") or not CAN_USE_PYREPL: - readline_module = readline - else: + + if CAN_USE_PYREPL: readline_module = _pyrepl.readline + exceptions = (OSError, *_pyrepl.unix_console._error) + else: + readline_module = readline + exceptions = OSError + try: readline_module.read_history_file(history) - except (OSError,* _pyrepl.unix_console._error): + except exceptions: pass def write_history(): diff --git a/Lib/statistics.py b/Lib/statistics.py index f193fcdc241aa9..e2b59267f04f68 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -248,6 +248,7 @@ def count_positive(iterable): found_zero = True else: raise StatisticsError('No negative inputs allowed', x) + total = fsum(map(log, count_positive(data))) if not n: @@ -710,6 +711,7 @@ def correlation(x, y, /, *, method='linear'): start = (n - 1) / -2 # Center rankings around zero x = _rank(x, start=start) y = _rank(y, start=start) + else: xbar = fsum(x) / n ybar = fsum(y) / n @@ -1213,91 +1215,6 @@ def quantiles(data, *, n=4, method='exclusive'): ## Normal Distribution ##################################################### -def _normal_dist_inv_cdf(p, mu, sigma): - # There is no closed-form solution to the inverse CDF for the normal - # distribution, so we use a rational approximation instead: - # Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the - # Normal Distribution". Applied Statistics. Blackwell Publishing. 37 - # (3): 477–484. doi:10.2307/2347330. JSTOR 2347330. - q = p - 0.5 - - if fabs(q) <= 0.425: - r = 0.180625 - q * q - # Hash sum: 55.88319_28806_14901_4439 - num = (((((((2.50908_09287_30122_6727e+3 * r + - 3.34305_75583_58812_8105e+4) * r + - 6.72657_70927_00870_0853e+4) * r + - 4.59219_53931_54987_1457e+4) * r + - 1.37316_93765_50946_1125e+4) * r + - 1.97159_09503_06551_4427e+3) * r + - 1.33141_66789_17843_7745e+2) * r + - 3.38713_28727_96366_6080e+0) * q - den = (((((((5.22649_52788_52854_5610e+3 * r + - 2.87290_85735_72194_2674e+4) * r + - 3.93078_95800_09271_0610e+4) * r + - 2.12137_94301_58659_5867e+4) * r + - 5.39419_60214_24751_1077e+3) * r + - 6.87187_00749_20579_0830e+2) * r + - 4.23133_30701_60091_1252e+1) * r + - 1.0) - x = num / den - return mu + (x * sigma) - - r = p if q <= 0.0 else 1.0 - p - r = sqrt(-log(r)) - if r <= 5.0: - r = r - 1.6 - # Hash sum: 49.33206_50330_16102_89036 - num = (((((((7.74545_01427_83414_07640e-4 * r + - 2.27238_44989_26918_45833e-2) * r + - 2.41780_72517_74506_11770e-1) * r + - 1.27045_82524_52368_38258e+0) * r + - 3.64784_83247_63204_60504e+0) * r + - 5.76949_72214_60691_40550e+0) * r + - 4.63033_78461_56545_29590e+0) * r + - 1.42343_71107_49683_57734e+0) - den = (((((((1.05075_00716_44416_84324e-9 * r + - 5.47593_80849_95344_94600e-4) * r + - 1.51986_66563_61645_71966e-2) * r + - 1.48103_97642_74800_74590e-1) * r + - 6.89767_33498_51000_04550e-1) * r + - 1.67638_48301_83803_84940e+0) * r + - 2.05319_16266_37758_82187e+0) * r + - 1.0) - else: - r = r - 5.0 - # Hash sum: 47.52583_31754_92896_71629 - num = (((((((2.01033_43992_92288_13265e-7 * r + - 2.71155_55687_43487_57815e-5) * r + - 1.24266_09473_88078_43860e-3) * r + - 2.65321_89526_57612_30930e-2) * r + - 2.96560_57182_85048_91230e-1) * r + - 1.78482_65399_17291_33580e+0) * r + - 5.46378_49111_64114_36990e+0) * r + - 6.65790_46435_01103_77720e+0) - den = (((((((2.04426_31033_89939_78564e-15 * r + - 1.42151_17583_16445_88870e-7) * r + - 1.84631_83175_10054_68180e-5) * r + - 7.86869_13114_56132_59100e-4) * r + - 1.48753_61290_85061_48525e-2) * r + - 1.36929_88092_27358_05310e-1) * r + - 5.99832_20655_58879_37690e-1) * r + - 1.0) - - x = num / den - if q < 0.0: - x = -x - - return mu + (x * sigma) - - -# If available, use C implementation -try: - from _statistics import _normal_dist_inv_cdf -except ImportError: - pass - - class NormalDist: "Normal distribution of a random variable" # https://en.wikipedia.org/wiki/Normal_distribution @@ -1561,11 +1478,13 @@ def _sum(data): types_add = types.add partials = {} partials_get = partials.get + for typ, values in groupby(data, type): types_add(typ) for n, d in map(_exact_ratio, values): count += 1 partials[d] = partials_get(d, 0) + n + if None in partials: # The sum will be a NAN or INF. We can ignore all the finite # partials, and just look at this special one. @@ -1574,6 +1493,7 @@ def _sum(data): else: # Sum all the partial sums using builtin sum. total = sum(Fraction(n, d) for d, n in partials.items()) + T = reduce(_coerce, types, int) # or raise TypeError return (T, total, count) @@ -1596,6 +1516,7 @@ def _ss(data, c=None): types_add = types.add sx_partials = defaultdict(int) sxx_partials = defaultdict(int) + for typ, values in groupby(data, type): types_add(typ) for n, d in map(_exact_ratio, values): @@ -1605,11 +1526,13 @@ def _ss(data, c=None): if not count: ssd = c = Fraction(0) + elif None in sx_partials: # The sum will be a NAN or INF. We can ignore all the finite # partials, and just look at this special one. ssd = c = sx_partials[None] assert not _isfinite(ssd) + else: sx = sum(Fraction(n, d) for d, n in sx_partials.items()) sxx = sum(Fraction(n, d*d) for d, n in sxx_partials.items()) @@ -1693,8 +1616,10 @@ def _convert(value, T): # This covers the cases where T is Fraction, or where value is # a NAN or INF (Decimal or float). return value + if issubclass(T, int) and value.denominator != 1: T = float + try: # FIXME: what do we do if this overflows? return T(value) @@ -1857,3 +1782,88 @@ def _sqrtprod(x: float, y: float) -> float: # https://www.wolframalpha.com/input/?i=Maclaurin+series+sqrt%28h**2+%2B+x%29+at+x%3D0 d = sumprod((x, h), (y, -h)) return h + d / (2.0 * h) + + +def _normal_dist_inv_cdf(p, mu, sigma): + # There is no closed-form solution to the inverse CDF for the normal + # distribution, so we use a rational approximation instead: + # Wichura, M.J. (1988). "Algorithm AS241: The Percentage Points of the + # Normal Distribution". Applied Statistics. Blackwell Publishing. 37 + # (3): 477–484. doi:10.2307/2347330. JSTOR 2347330. + q = p - 0.5 + + if fabs(q) <= 0.425: + r = 0.180625 - q * q + # Hash sum: 55.88319_28806_14901_4439 + num = (((((((2.50908_09287_30122_6727e+3 * r + + 3.34305_75583_58812_8105e+4) * r + + 6.72657_70927_00870_0853e+4) * r + + 4.59219_53931_54987_1457e+4) * r + + 1.37316_93765_50946_1125e+4) * r + + 1.97159_09503_06551_4427e+3) * r + + 1.33141_66789_17843_7745e+2) * r + + 3.38713_28727_96366_6080e+0) * q + den = (((((((5.22649_52788_52854_5610e+3 * r + + 2.87290_85735_72194_2674e+4) * r + + 3.93078_95800_09271_0610e+4) * r + + 2.12137_94301_58659_5867e+4) * r + + 5.39419_60214_24751_1077e+3) * r + + 6.87187_00749_20579_0830e+2) * r + + 4.23133_30701_60091_1252e+1) * r + + 1.0) + x = num / den + return mu + (x * sigma) + + r = p if q <= 0.0 else 1.0 - p + r = sqrt(-log(r)) + if r <= 5.0: + r = r - 1.6 + # Hash sum: 49.33206_50330_16102_89036 + num = (((((((7.74545_01427_83414_07640e-4 * r + + 2.27238_44989_26918_45833e-2) * r + + 2.41780_72517_74506_11770e-1) * r + + 1.27045_82524_52368_38258e+0) * r + + 3.64784_83247_63204_60504e+0) * r + + 5.76949_72214_60691_40550e+0) * r + + 4.63033_78461_56545_29590e+0) * r + + 1.42343_71107_49683_57734e+0) + den = (((((((1.05075_00716_44416_84324e-9 * r + + 5.47593_80849_95344_94600e-4) * r + + 1.51986_66563_61645_71966e-2) * r + + 1.48103_97642_74800_74590e-1) * r + + 6.89767_33498_51000_04550e-1) * r + + 1.67638_48301_83803_84940e+0) * r + + 2.05319_16266_37758_82187e+0) * r + + 1.0) + else: + r = r - 5.0 + # Hash sum: 47.52583_31754_92896_71629 + num = (((((((2.01033_43992_92288_13265e-7 * r + + 2.71155_55687_43487_57815e-5) * r + + 1.24266_09473_88078_43860e-3) * r + + 2.65321_89526_57612_30930e-2) * r + + 2.96560_57182_85048_91230e-1) * r + + 1.78482_65399_17291_33580e+0) * r + + 5.46378_49111_64114_36990e+0) * r + + 6.65790_46435_01103_77720e+0) + den = (((((((2.04426_31033_89939_78564e-15 * r + + 1.42151_17583_16445_88870e-7) * r + + 1.84631_83175_10054_68180e-5) * r + + 7.86869_13114_56132_59100e-4) * r + + 1.48753_61290_85061_48525e-2) * r + + 1.36929_88092_27358_05310e-1) * r + + 5.99832_20655_58879_37690e-1) * r + + 1.0) + + x = num / den + if q < 0.0: + x = -x + + return mu + (x * sigma) + + +# If available, use C implementation +try: + from _statistics import _normal_dist_inv_cdf +except ImportError: + pass diff --git a/Lib/test/certdata/cert3.pem b/Lib/test/certdata/cert3.pem index 034bc43ff1974e..4ab0f5ff133e3f 100644 --- a/Lib/test/certdata/cert3.pem +++ b/Lib/test/certdata/cert3.pem @@ -31,4 +31,4 @@ zqmtEM65ceSP8lo8Zbrcy+AEkCulFaZ92tyjtbe8oN4wTmTLFw06oFLSZzuiOgDV OaphdVKf/pvA6KBpr6izox0KQFIE5z3AAJZfKzMGDDD20xhy7jjQZNMAhjfsT+k4 SeYB/6KafNxq08uoulj7w4Z4R/EGpkXnU96ZHYHmvGN0RnxwI1cpYHCazG8AjsK/ anN9brBi5twTGrn+D8LRBqF5Yn+2MKkD0EdXJdtIENHP+32sPQ== ------END CERTIFICATE----- \ No newline at end of file +-----END CERTIFICATE----- diff --git a/Lib/test/certdata/make_ssl_certs.py b/Lib/test/certdata/make_ssl_certs.py index 5e626baf550c5b..198c64035c5044 100644 --- a/Lib/test/certdata/make_ssl_certs.py +++ b/Lib/test/certdata/make_ssl_certs.py @@ -139,7 +139,6 @@ def make_cert_key(cmdlineargs, hostname, sign=False, extra_san='', f.write(req) args = ['req', '-new', '-nodes', '-days', cmdlineargs.days, '-newkey', key, '-keyout', key_file, - '-extensions', ext, '-config', req_file] if sign: with tempfile.NamedTemporaryFile(delete=False) as f: @@ -148,7 +147,7 @@ def make_cert_key(cmdlineargs, hostname, sign=False, extra_san='', args += ['-out', reqfile ] else: - args += ['-x509', '-out', cert_file ] + args += ['-extensions', ext, '-x509', '-out', cert_file ] check_call(['openssl'] + args) if sign: @@ -266,6 +265,8 @@ def write_cert_reference(path): f.write(key) f.write(cert) + check_call(['openssl', 'x509', '-outform', 'pem', '-in', 'keycert3.pem', '-out', 'cert3.pem']) + cert, key = make_cert_key(cmdlineargs, 'fakehostname', sign=True) with open('keycert4.pem', 'w') as f: f.write(key) diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py index 1722cc8612ca6b..8ef8fae44f1d25 100644 --- a/Lib/test/pickletester.py +++ b/Lib/test/pickletester.py @@ -26,7 +26,7 @@ from test import support from test.support import os_helper from test.support import ( - TestFailed, run_with_locale, no_tracing, + TestFailed, run_with_locales, no_tracing, _2G, _4G, bigmemtest ) from test.support.import_helper import forget @@ -2895,7 +2895,7 @@ def test_float(self): got = self.loads(pickle) self.assert_is_copy(value, got) - @run_with_locale('LC_ALL', 'de_DE', 'fr_FR') + @run_with_locales('LC_ALL', 'de_DE', 'fr_FR', '') def test_float_format(self): # make sure that floats are formatted locale independent with proto 0 self.assertEqual(self.dumps(1.2, 0)[0:3], b'F1.') diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 99cb10fc7b5f7b..72ce5dacd1be4c 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -930,8 +930,8 @@ def check_sizeof(test, o, size): test.assertEqual(result, size, msg) #======================================================================= -# Decorator for running a function in a different locale, correctly resetting -# it afterwards. +# Decorator/context manager for running a code in a different locale, +# correctly resetting it afterwards. @contextlib.contextmanager def run_with_locale(catstr, *locales): @@ -942,16 +942,21 @@ def run_with_locale(catstr, *locales): except AttributeError: # if the test author gives us an invalid category string raise - except: + except Exception: # cannot retrieve original locale, so do nothing locale = orig_locale = None + if '' not in locales: + raise unittest.SkipTest('no locales') else: for loc in locales: try: locale.setlocale(category, loc) break - except: + except locale.Error: pass + else: + if '' not in locales: + raise unittest.SkipTest(f'no locales {locales}') try: yield @@ -959,6 +964,46 @@ def run_with_locale(catstr, *locales): if locale and orig_locale: locale.setlocale(category, orig_locale) +#======================================================================= +# Decorator for running a function in multiple locales (if they are +# availasble) and resetting the original locale afterwards. + +def run_with_locales(catstr, *locales): + def deco(func): + @functools.wraps(func) + def wrapper(self, /, *args, **kwargs): + dry_run = '' in locales + try: + import locale + category = getattr(locale, catstr) + orig_locale = locale.setlocale(category) + except AttributeError: + # if the test author gives us an invalid category string + raise + except Exception: + # cannot retrieve original locale, so do nothing + pass + else: + try: + for loc in locales: + with self.subTest(locale=loc): + try: + locale.setlocale(category, loc) + except locale.Error: + self.skipTest(f'no locale {loc!r}') + else: + dry_run = False + func(self, *args, **kwargs) + finally: + locale.setlocale(category, orig_locale) + if dry_run: + # no locales available, so just run the test + # with the current locale + with self.subTest(locale=None): + func(self, *args, **kwargs) + return wrapper + return deco + #======================================================================= # Decorator for running a function in a specific timezone, correctly # resetting it afterwards. @@ -2907,10 +2952,11 @@ def in_systemd_nspawn_sync_suppressed() -> bool: # trigger EINVAL. Otherwise, ENOENT will be given instead. import errno try: - with os.open(__file__, os.O_RDONLY | os.O_SYNC): - pass + fd = os.open(__file__, os.O_RDONLY | os.O_SYNC) except OSError as err: if err.errno == errno.EINVAL: return True + else: + os.close(fd) return False diff --git a/Lib/test/support/import_helper.py b/Lib/test/support/import_helper.py index edcd2b9a35bbd9..2b91bdcf9cd859 100644 --- a/Lib/test/support/import_helper.py +++ b/Lib/test/support/import_helper.py @@ -58,8 +58,8 @@ def make_legacy_pyc(source): :return: The file system path to the legacy pyc file. """ pyc_file = importlib.util.cache_from_source(source) - up_one = os.path.dirname(os.path.abspath(source)) - legacy_pyc = os.path.join(up_one, source + 'c') + assert source.endswith('.py') + legacy_pyc = source + 'c' shutil.move(pyc_file, legacy_pyc) return legacy_pyc diff --git a/Lib/test/test__locale.py b/Lib/test/test__locale.py index 0947464bb8c04e..ba2d31f9c1ee9d 100644 --- a/Lib/test/test__locale.py +++ b/Lib/test/test__locale.py @@ -115,16 +115,17 @@ def numeric_tester(self, calc_type, calc_value, data_type, used_locale): def test_lc_numeric_nl_langinfo(self): # Test nl_langinfo against known values tested = False + oldloc = setlocale(LC_CTYPE) for loc in candidate_locales: try: setlocale(LC_NUMERIC, loc) - setlocale(LC_CTYPE, loc) except Error: continue for li, lc in ((RADIXCHAR, "decimal_point"), (THOUSEP, "thousands_sep")): if self.numeric_tester('nl_langinfo', nl_langinfo(li), lc, loc): tested = True + self.assertEqual(setlocale(LC_CTYPE), oldloc) if not tested: self.skipTest('no suitable locales') @@ -135,10 +136,10 @@ def test_lc_numeric_nl_langinfo(self): def test_lc_numeric_localeconv(self): # Test localeconv against known values tested = False + oldloc = setlocale(LC_CTYPE) for loc in candidate_locales: try: setlocale(LC_NUMERIC, loc) - setlocale(LC_CTYPE, loc) except Error: continue formatting = localeconv() @@ -146,6 +147,7 @@ def test_lc_numeric_localeconv(self): "thousands_sep"): if self.numeric_tester('localeconv', formatting[lc], lc, loc): tested = True + self.assertEqual(setlocale(LC_CTYPE), oldloc) if not tested: self.skipTest('no suitable locales') @@ -153,10 +155,10 @@ def test_lc_numeric_localeconv(self): def test_lc_numeric_basic(self): # Test nl_langinfo against localeconv tested = False + oldloc = setlocale(LC_CTYPE) for loc in candidate_locales: try: setlocale(LC_NUMERIC, loc) - setlocale(LC_CTYPE, loc) except Error: continue for li, lc in ((RADIXCHAR, "decimal_point"), @@ -173,6 +175,7 @@ def test_lc_numeric_basic(self): nl_radixchar, li_radixchar, loc, set_locale)) tested = True + self.assertEqual(setlocale(LC_CTYPE), oldloc) if not tested: self.skipTest('no suitable locales') @@ -180,10 +183,10 @@ def test_float_parsing(self): # Bug #1391872: Test whether float parsing is okay on European # locales. tested = False + oldloc = setlocale(LC_CTYPE) for loc in candidate_locales: try: setlocale(LC_NUMERIC, loc) - setlocale(LC_CTYPE, loc) except Error: continue @@ -199,6 +202,7 @@ def test_float_parsing(self): self.assertRaises(ValueError, float, localeconv()['decimal_point'].join(['1', '23'])) tested = True + self.assertEqual(setlocale(LC_CTYPE), oldloc) if not tested: self.skipTest('no suitable locales') diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index a972ed0cc9053b..1bf812b36fc2c6 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -6,6 +6,7 @@ import io import operator import os +import py_compile import shutil import stat import sys @@ -15,10 +16,16 @@ import argparse import warnings -from test.support import os_helper, captured_stderr +from test.support import captured_stderr +from test.support import import_helper +from test.support import os_helper +from test.support import script_helper from unittest import mock +py = os.path.basename(sys.executable) + + class StdIOBuffer(io.TextIOWrapper): '''Replacement for writable io.StringIO that behaves more like real file @@ -2780,8 +2787,6 @@ def setUp(self): group.add_argument('-a', action='store_true') group.add_argument('-b', action='store_true') - self.main_program = os.path.basename(sys.argv[0]) - def test_single_parent(self): parser = ErrorRaisingArgumentParser(parents=[self.wxyz_parent]) self.assertEqual(parser.parse_args('-y 1 2 --w 3'.split()), @@ -2871,11 +2876,10 @@ def test_subparser_parents_mutex(self): def test_parent_help(self): parents = [self.abcd_parent, self.wxyz_parent] - parser = ErrorRaisingArgumentParser(parents=parents) + parser = ErrorRaisingArgumentParser(prog='PROG', parents=parents) parser_help = parser.format_help() - progname = self.main_program self.assertEqual(parser_help, textwrap.dedent('''\ - usage: {}{}[-h] [-b B] [--d D] [--w W] [-y Y] a z + usage: PROG [-h] [-b B] [--d D] [--w W] [-y Y] a z positional arguments: a @@ -2891,7 +2895,7 @@ def test_parent_help(self): x: -y Y - '''.format(progname, ' ' if progname else '' ))) + ''')) def test_groups_parents(self): parent = ErrorRaisingArgumentParser(add_help=False) @@ -2901,15 +2905,14 @@ def test_groups_parents(self): m = parent.add_mutually_exclusive_group() m.add_argument('-y') m.add_argument('-z') - parser = ErrorRaisingArgumentParser(parents=[parent]) + parser = ErrorRaisingArgumentParser(prog='PROG', parents=[parent]) self.assertRaises(ArgumentParserError, parser.parse_args, ['-y', 'Y', '-z', 'Z']) parser_help = parser.format_help() - progname = self.main_program self.assertEqual(parser_help, textwrap.dedent('''\ - usage: {}{}[-h] [-w W] [-x X] [-y Y | -z Z] + usage: PROG [-h] [-w W] [-x X] [-y Y | -z Z] options: -h, --help show this help message and exit @@ -2921,7 +2924,7 @@ def test_groups_parents(self): -w W -x X - '''.format(progname, ' ' if progname else '' ))) + ''')) def test_wrong_type_parents(self): self.assertRaises(TypeError, ErrorRaisingArgumentParser, parents=[1]) @@ -4895,7 +4898,7 @@ class TestHelpNone(HelpTestCase): version = '' -class TestHelpTupleMetavar(HelpTestCase): +class TestHelpTupleMetavarOptional(HelpTestCase): """Test specifying metavar as a tuple""" parser_signature = Sig(prog='PROG') @@ -4922,6 +4925,34 @@ class TestHelpTupleMetavar(HelpTestCase): version = '' +class TestHelpTupleMetavarPositional(HelpTestCase): + """Test specifying metavar on a Positional as a tuple""" + + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('w', help='w help', nargs='+', metavar=('W1', 'W2')), + Sig('x', help='x help', nargs='*', metavar=('X1', 'X2')), + Sig('y', help='y help', nargs=3, metavar=('Y1', 'Y2', 'Y3')), + Sig('z', help='z help', nargs='?', metavar=('Z1',)), + ] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] W1 [W2 ...] [X1 [X2 ...]] Y1 Y2 Y3 [Z1] + ''' + help = usage + '''\ + + positional arguments: + W1 W2 w help + X1 X2 x help + Y1 Y2 Y3 y help + Z1 z help + + options: + -h, --help show this help message and exit + ''' + version = '' + + class TestHelpRawText(HelpTestCase): """Test the RawTextHelpFormatter""" @@ -5262,15 +5293,15 @@ def custom_formatter(prog): class TestInvalidArgumentConstructors(TestCase): """Test a bunch of invalid Argument constructors""" - def assertTypeError(self, *args, **kwargs): + def assertTypeError(self, *args, errmsg=None, **kwargs): parser = argparse.ArgumentParser() - self.assertRaises(TypeError, parser.add_argument, - *args, **kwargs) + self.assertRaisesRegex(TypeError, errmsg, parser.add_argument, + *args, **kwargs) - def assertValueError(self, *args, **kwargs): + def assertValueError(self, *args, errmsg=None, **kwargs): parser = argparse.ArgumentParser() - self.assertRaises(ValueError, parser.add_argument, - *args, **kwargs) + self.assertRaisesRegex(ValueError, errmsg, parser.add_argument, + *args, **kwargs) def test_invalid_keyword_arguments(self): self.assertTypeError('-x', bar=None) @@ -5280,8 +5311,9 @@ def test_invalid_keyword_arguments(self): def test_missing_destination(self): self.assertTypeError() - for action in ['append', 'store']: - self.assertTypeError(action=action) + for action in ['store', 'append', 'extend']: + with self.subTest(action=action): + self.assertTypeError(action=action) def test_invalid_option_strings(self): self.assertValueError('--') @@ -5298,10 +5330,8 @@ def test_invalid_action(self): self.assertValueError('-x', action='foo') self.assertValueError('foo', action='baz') self.assertValueError('--foo', action=('store', 'append')) - parser = argparse.ArgumentParser() - with self.assertRaises(ValueError) as cm: - parser.add_argument("--foo", action="store-true") - self.assertIn('unknown action', str(cm.exception)) + self.assertValueError('--foo', action="store-true", + errmsg='unknown action') def test_multiple_dest(self): parser = argparse.ArgumentParser() @@ -5314,39 +5344,47 @@ def test_multiple_dest(self): def test_no_argument_actions(self): for action in ['store_const', 'store_true', 'store_false', 'append_const', 'count']: - for attrs in [dict(type=int), dict(nargs='+'), - dict(choices=['a', 'b'])]: - self.assertTypeError('-x', action=action, **attrs) + with self.subTest(action=action): + for attrs in [dict(type=int), dict(nargs='+'), + dict(choices=['a', 'b'])]: + with self.subTest(attrs=attrs): + self.assertTypeError('-x', action=action, **attrs) + self.assertTypeError('x', action=action, **attrs) + self.assertTypeError('-x', action=action, nargs=0) + self.assertTypeError('x', action=action, nargs=0) def test_no_argument_no_const_actions(self): # options with zero arguments for action in ['store_true', 'store_false', 'count']: + with self.subTest(action=action): + # const is always disallowed + self.assertTypeError('-x', const='foo', action=action) - # const is always disallowed - self.assertTypeError('-x', const='foo', action=action) - - # nargs is always disallowed - self.assertTypeError('-x', nargs='*', action=action) + # nargs is always disallowed + self.assertTypeError('-x', nargs='*', action=action) def test_more_than_one_argument_actions(self): - for action in ['store', 'append']: - - # nargs=0 is disallowed - self.assertValueError('-x', nargs=0, action=action) - self.assertValueError('spam', nargs=0, action=action) - - # const is disallowed with non-optional arguments - for nargs in [1, '*', '+']: - self.assertValueError('-x', const='foo', - nargs=nargs, action=action) - self.assertValueError('spam', const='foo', - nargs=nargs, action=action) + for action in ['store', 'append', 'extend']: + with self.subTest(action=action): + # nargs=0 is disallowed + action_name = 'append' if action == 'extend' else action + self.assertValueError('-x', nargs=0, action=action, + errmsg=f'nargs for {action_name} actions must be != 0') + self.assertValueError('spam', nargs=0, action=action, + errmsg=f'nargs for {action_name} actions must be != 0') + + # const is disallowed with non-optional arguments + for nargs in [1, '*', '+']: + self.assertValueError('-x', const='foo', + nargs=nargs, action=action) + self.assertValueError('spam', const='foo', + nargs=nargs, action=action) def test_required_const_actions(self): for action in ['store_const', 'append_const']: - - # nargs is always disallowed - self.assertTypeError('-x', nargs='+', action=action) + with self.subTest(action=action): + # nargs is always disallowed + self.assertTypeError('-x', nargs='+', action=action) def test_parsers_action_missing_params(self): self.assertTypeError('command', action='parsers') @@ -6518,6 +6556,27 @@ def test_required_args(self): 'the following arguments are required: bar, baz$', self.parser.parse_args, []) + def test_required_args_with_metavar(self): + self.parser.add_argument('bar') + self.parser.add_argument('baz', metavar='BaZ') + self.assertRaisesRegex(argparse.ArgumentError, + 'the following arguments are required: bar, BaZ$', + self.parser.parse_args, []) + + def test_required_args_n(self): + self.parser.add_argument('bar') + self.parser.add_argument('baz', nargs=3) + self.assertRaisesRegex(argparse.ArgumentError, + 'the following arguments are required: bar, baz$', + self.parser.parse_args, []) + + def test_required_args_n_with_metavar(self): + self.parser.add_argument('bar') + self.parser.add_argument('baz', nargs=3, metavar=('B', 'A', 'Z')) + self.assertRaisesRegex(argparse.ArgumentError, + 'the following arguments are required: bar, B, A, Z$', + self.parser.parse_args, []) + def test_required_args_optional(self): self.parser.add_argument('bar') self.parser.add_argument('baz', nargs='?') @@ -6532,6 +6591,20 @@ def test_required_args_zero_or_more(self): 'the following arguments are required: bar$', self.parser.parse_args, []) + def test_required_args_one_or_more(self): + self.parser.add_argument('bar') + self.parser.add_argument('baz', nargs='+') + self.assertRaisesRegex(argparse.ArgumentError, + 'the following arguments are required: bar, baz$', + self.parser.parse_args, []) + + def test_required_args_one_or_more_with_metavar(self): + self.parser.add_argument('bar') + self.parser.add_argument('baz', nargs='+', metavar=('BaZ1', 'BaZ2')) + self.assertRaisesRegex(argparse.ArgumentError, + r'the following arguments are required: bar, BaZ1\[, BaZ2]$', + self.parser.parse_args, []) + def test_required_args_remainder(self): self.parser.add_argument('bar') self.parser.add_argument('baz', nargs='...') @@ -6547,6 +6620,39 @@ def test_required_mutually_exclusive_args(self): 'one of the arguments --bar --baz is required', self.parser.parse_args, []) + def test_conflicting_mutually_exclusive_args_optional_with_metavar(self): + group = self.parser.add_mutually_exclusive_group() + group.add_argument('--bar') + group.add_argument('baz', nargs='?', metavar='BaZ') + self.assertRaisesRegex(argparse.ArgumentError, + 'argument BaZ: not allowed with argument --bar$', + self.parser.parse_args, ['--bar', 'a', 'b']) + self.assertRaisesRegex(argparse.ArgumentError, + 'argument --bar: not allowed with argument BaZ$', + self.parser.parse_args, ['a', '--bar', 'b']) + + def test_conflicting_mutually_exclusive_args_zero_or_more_with_metavar1(self): + group = self.parser.add_mutually_exclusive_group() + group.add_argument('--bar') + group.add_argument('baz', nargs='*', metavar=('BAZ1',)) + self.assertRaisesRegex(argparse.ArgumentError, + 'argument BAZ1: not allowed with argument --bar$', + self.parser.parse_args, ['--bar', 'a', 'b']) + self.assertRaisesRegex(argparse.ArgumentError, + 'argument --bar: not allowed with argument BAZ1$', + self.parser.parse_args, ['a', '--bar', 'b']) + + def test_conflicting_mutually_exclusive_args_zero_or_more_with_metavar2(self): + group = self.parser.add_mutually_exclusive_group() + group.add_argument('--bar') + group.add_argument('baz', nargs='*', metavar=('BAZ1', 'BAZ2')) + self.assertRaisesRegex(argparse.ArgumentError, + r'argument BAZ1\[, BAZ2]: not allowed with argument --bar$', + self.parser.parse_args, ['--bar', 'a', 'b']) + self.assertRaisesRegex(argparse.ArgumentError, + r'argument --bar: not allowed with argument BAZ1\[, BAZ2]$', + self.parser.parse_args, ['a', '--bar', 'b']) + def test_ambiguous_option(self): self.parser.add_argument('--foobaz') self.parser.add_argument('--fooble', action='store_true') @@ -6561,6 +6667,99 @@ def test_os_error(self): self.parser.parse_args, ['@no-such-file']) +class TestProgName(TestCase): + source = textwrap.dedent('''\ + import argparse + parser = argparse.ArgumentParser() + parser.parse_args() + ''') + + def setUp(self): + self.dirname = 'package' + os_helper.FS_NONASCII + self.addCleanup(os_helper.rmtree, self.dirname) + os.mkdir(self.dirname) + + def make_script(self, dirname, basename, *, compiled=False): + script_name = script_helper.make_script(dirname, basename, self.source) + if not compiled: + return script_name + py_compile.compile(script_name, doraise=True) + os.remove(script_name) + pyc_file = import_helper.make_legacy_pyc(script_name) + return pyc_file + + def make_zip_script(self, script_name, name_in_zip=None): + zip_name, _ = script_helper.make_zip_script(self.dirname, 'test_zip', + script_name, name_in_zip) + return zip_name + + def check_usage(self, expected, *args, **kwargs): + res = script_helper.assert_python_ok('-Xutf8', *args, '-h', **kwargs) + self.assertEqual(res.out.splitlines()[0].decode(), + f'usage: {expected} [-h]') + + def test_script(self, compiled=False): + basename = os_helper.TESTFN + script_name = self.make_script(self.dirname, basename, compiled=compiled) + self.check_usage(os.path.basename(script_name), script_name, '-h') + + def test_script_compiled(self): + self.test_script(compiled=True) + + def test_directory(self, compiled=False): + dirname = os.path.join(self.dirname, os_helper.TESTFN) + os.mkdir(dirname) + self.make_script(dirname, '__main__', compiled=compiled) + self.check_usage(f'{py} {dirname}', dirname) + dirname2 = os.path.join(os.curdir, dirname) + self.check_usage(f'{py} {dirname2}', dirname2) + + def test_directory_compiled(self): + self.test_directory(compiled=True) + + def test_module(self, compiled=False): + basename = 'module' + os_helper.FS_NONASCII + modulename = f'{self.dirname}.{basename}' + self.make_script(self.dirname, basename, compiled=compiled) + self.check_usage(f'{py} -m {modulename}', + '-m', modulename, PYTHONPATH=os.curdir) + + def test_module_compiled(self): + self.test_module(compiled=True) + + def test_package(self, compiled=False): + basename = 'subpackage' + os_helper.FS_NONASCII + packagename = f'{self.dirname}.{basename}' + subdirname = os.path.join(self.dirname, basename) + os.mkdir(subdirname) + self.make_script(subdirname, '__main__', compiled=compiled) + self.check_usage(f'{py} -m {packagename}', + '-m', packagename, PYTHONPATH=os.curdir) + self.check_usage(f'{py} -m {packagename}', + '-m', packagename + '.__main__', PYTHONPATH=os.curdir) + + def test_package_compiled(self): + self.test_package(compiled=True) + + def test_zipfile(self, compiled=False): + script_name = self.make_script(self.dirname, '__main__', compiled=compiled) + zip_name = self.make_zip_script(script_name) + self.check_usage(f'{py} {zip_name}', zip_name) + + def test_zipfile_compiled(self): + self.test_zipfile(compiled=True) + + def test_directory_in_zipfile(self, compiled=False): + script_name = self.make_script(self.dirname, '__main__', compiled=compiled) + name_in_zip = 'package/subpackage/__main__' + ('.py', '.pyc')[compiled] + zip_name = self.make_zip_script(script_name, name_in_zip) + dirname = os.path.join(zip_name, 'package', 'subpackage') + self.check_usage(f'{py} {dirname}', dirname) + + def test_directory_in_zipfile_compiled(self): + self.test_directory_in_zipfile(compiled=True) + + def tearDownModule(): # Remove global references to avoid looking like we have refleaks. RFile.seen = {} diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index f052822cb45273..01d2e392302e86 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -789,6 +789,13 @@ def test_repr(self) -> None: with self.subTest(test_input=test): self.assertEqual(repr(ast.parse(test)), snapshot) + def test_repr_large_input_crash(self): + # gh-125010: Fix use-after-free in ast repr() + source = "0x0" + "e" * 10_000 + with self.assertRaisesRegex(ValueError, + r"Exceeds the limit \(\d+ digits\)"): + repr(ast.Constant(value=eval(source))) + class CopyTests(unittest.TestCase): """Test copying and pickling AST nodes.""" diff --git a/Lib/test/test_asyncio/test_eager_task_factory.py b/Lib/test/test_asyncio/test_eager_task_factory.py index 1579ad1188d725..0777f39b572486 100644 --- a/Lib/test/test_asyncio/test_eager_task_factory.py +++ b/Lib/test/test_asyncio/test_eager_task_factory.py @@ -213,53 +213,6 @@ async def run(): self.run_coro(run()) - def test_staggered_race_with_eager_tasks(self): - # See https://github.com/python/cpython/issues/124309 - - async def fail(): - await asyncio.sleep(0) - raise ValueError("no good") - - async def run(): - winner, index, excs = await asyncio.staggered.staggered_race( - [ - lambda: asyncio.sleep(2, result="sleep2"), - lambda: asyncio.sleep(1, result="sleep1"), - lambda: fail() - ], - delay=0.25 - ) - self.assertEqual(winner, 'sleep1') - self.assertEqual(index, 1) - self.assertIsNone(excs[index]) - self.assertIsInstance(excs[0], asyncio.CancelledError) - self.assertIsInstance(excs[2], ValueError) - - self.run_coro(run()) - - def test_staggered_race_with_eager_tasks_no_delay(self): - # See https://github.com/python/cpython/issues/124309 - async def fail(): - raise ValueError("no good") - - async def run(): - winner, index, excs = await asyncio.staggered.staggered_race( - [ - lambda: fail(), - lambda: asyncio.sleep(1, result="sleep1"), - lambda: asyncio.sleep(0, result="sleep0"), - ], - delay=None - ) - self.assertEqual(winner, 'sleep1') - self.assertEqual(index, 1) - self.assertIsNone(excs[index]) - self.assertIsInstance(excs[0], ValueError) - self.assertEqual(len(excs), 2) - - self.run_coro(run()) - - class PyEagerTaskFactoryLoopTests(EagerTaskFactoryLoopTests, test_utils.TestCase): Task = tasks._PyTask diff --git a/Lib/test/test_asyncio/test_staggered.py b/Lib/test/test_asyncio/test_staggered.py index 8cd98394aea8f8..e6e32f7dbbbcba 100644 --- a/Lib/test/test_asyncio/test_staggered.py +++ b/Lib/test/test_asyncio/test_staggered.py @@ -82,64 +82,16 @@ async def test_none_successful(self): async def coro(index): raise ValueError(index) - for delay in [None, 0, 0.1, 1]: - with self.subTest(delay=delay): - winner, index, excs = await staggered_race( - [ - lambda: coro(0), - lambda: coro(1), - ], - delay=delay, - ) - - self.assertIs(winner, None) - self.assertIs(index, None) - self.assertEqual(len(excs), 2) - self.assertIsInstance(excs[0], ValueError) - self.assertIsInstance(excs[1], ValueError) - - async def test_long_delay_early_failure(self): - async def coro(index): - await asyncio.sleep(0) # Dummy coroutine for the 1 case - if index == 0: - await asyncio.sleep(0.1) # Dummy coroutine - raise ValueError(index) - - return f'Res: {index}' - winner, index, excs = await staggered_race( [ lambda: coro(0), lambda: coro(1), ], - delay=10, + delay=None, ) - self.assertEqual(winner, 'Res: 1') - self.assertEqual(index, 1) + self.assertIs(winner, None) + self.assertIs(index, None) self.assertEqual(len(excs), 2) self.assertIsInstance(excs[0], ValueError) - self.assertIsNone(excs[1]) - - def test_loop_argument(self): - loop = asyncio.new_event_loop() - async def coro(): - self.assertEqual(loop, asyncio.get_running_loop()) - return 'coro' - - async def main(): - winner, index, excs = await staggered_race( - [coro], - delay=0.1, - loop=loop - ) - - self.assertEqual(winner, 'coro') - self.assertEqual(index, 0) - - loop.run_until_complete(main()) - loop.close() - - -if __name__ == "__main__": - unittest.main() + self.assertIsInstance(excs[1], ValueError) diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py index d32b7ff251885d..dbe5646c2b7c08 100644 --- a/Lib/test/test_asyncio/test_streams.py +++ b/Lib/test/test_asyncio/test_streams.py @@ -1200,6 +1200,24 @@ async def handle_echo(reader, writer): messages = self._basetest_unhandled_exceptions(handle_echo) self.assertEqual(messages, []) + def test_open_connection_happy_eyeball_refcycles(self): + port = socket_helper.find_unused_port() + async def main(): + exc = None + try: + await asyncio.open_connection( + host="localhost", + port=port, + happy_eyeballs_delay=0.25, + ) + except* OSError as excs: + # can't use assertRaises because that clears frames + exc = excs.exceptions[0] + self.assertIsNotNone(exc) + self.assertListEqual(gc.get_referrers(exc), [main_coro]) + main_coro = main() + asyncio.run(main_coro) + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py index 1f9ffc5e9a5c33..f119d89c0ec39a 100644 --- a/Lib/test/test_calendar.py +++ b/Lib/test/test_calendar.py @@ -985,7 +985,7 @@ def assertFailure(self, *args): def test_help(self): stdout = self.run_cmd_ok('-h') self.assertIn(b'usage:', stdout) - self.assertIn(b'calendar.py', stdout) + self.assertIn(b' -m calendar ', stdout) self.assertIn(b'--help', stdout) # special case: stdout but sys.exit() diff --git a/Lib/test/test_capi/test_unicode.py b/Lib/test/test_capi/test_unicode.py index e6f85427214958..65d8242ad3fc60 100644 --- a/Lib/test/test_capi/test_unicode.py +++ b/Lib/test/test_capi/test_unicode.py @@ -1903,6 +1903,39 @@ def test_recover_error(self): self.assertEqual(writer.finish(), 'Hello World.') + def test_unicode_equal(self): + unicode_equal = _testlimitedcapi.unicode_equal + + def copy(text): + return text.encode().decode() + + self.assertTrue(unicode_equal("", "")) + self.assertTrue(unicode_equal("abc", "abc")) + self.assertTrue(unicode_equal("abc", copy("abc"))) + self.assertTrue(unicode_equal("\u20ac", copy("\u20ac"))) + self.assertTrue(unicode_equal("\U0010ffff", copy("\U0010ffff"))) + + self.assertFalse(unicode_equal("abc", "abcd")) + self.assertFalse(unicode_equal("\u20ac", "\u20ad")) + self.assertFalse(unicode_equal("\U0010ffff", "\U0010fffe")) + + # str subclass + self.assertTrue(unicode_equal("abc", Str("abc"))) + self.assertTrue(unicode_equal(Str("abc"), "abc")) + self.assertFalse(unicode_equal("abc", Str("abcd"))) + self.assertFalse(unicode_equal(Str("abc"), "abcd")) + + # invalid type + for invalid_type in (b'bytes', 123, ("tuple",)): + with self.subTest(invalid_type=invalid_type): + with self.assertRaises(TypeError): + unicode_equal("abc", invalid_type) + with self.assertRaises(TypeError): + unicode_equal(invalid_type, "abc") + + # CRASHES unicode_equal("abc", NULL) + # CRASHES unicode_equal(NULL, "abc") + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 428036e1765b8f..290656f070503a 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -2,7 +2,6 @@ import contextlib import copy import io -import locale import pickle import sys import unittest @@ -1812,16 +1811,10 @@ def test_getwriter(self): self.assertRaises(TypeError, codecs.getwriter) self.assertRaises(LookupError, codecs.getwriter, "__spam__") + @support.run_with_locale('LC_CTYPE', 'tr_TR') def test_lookup_issue1813(self): # Issue #1813: under Turkish locales, lookup of some codecs failed # because 'I' is lowercased as "ı" (dotless i) - oldlocale = locale.setlocale(locale.LC_CTYPE) - self.addCleanup(locale.setlocale, locale.LC_CTYPE, oldlocale) - try: - locale.setlocale(locale.LC_CTYPE, 'tr_TR') - except locale.Error: - # Unsupported locale on this system - self.skipTest('test needs Turkish locale') c = codecs.lookup('ASCII') self.assertEqual(c.name, 'ascii') diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index f7ef7a1c26f7bd..6f838da6018741 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -13,7 +13,10 @@ import types import textwrap import warnings -import _testinternalcapi +try: + import _testinternalcapi +except ImportError: + _testinternalcapi = None from test import support from test.support import (script_helper, requires_debug_ranges, run_code, @@ -476,6 +479,19 @@ def test_dead_code_with_except_handler_compiles(self): x = 2 """), '', 'exec') + def test_try_except_in_while_with_chained_condition_compiles(self): + # see gh-124871 + compile(textwrap.dedent(""" + name_1, name_2, name_3 = 1, 2, 3 + while name_3 <= name_2 > name_1: + try: + raise + except: + pass + finally: + pass + """), '', 'exec') + def test_compile_invalid_namedexpr(self): # gh-109351 m = ast.Module( @@ -1370,6 +1386,14 @@ def check_op_count(func, op, expected): actual += 1 self.assertEqual(actual, expected) + def check_consts(func, typ, expected): + slice_consts = 0 + consts = func.__code__.co_consts + for instr in dis.Bytecode(func): + if instr.opname == "LOAD_CONST" and isinstance(consts[instr.oparg], typ): + slice_consts += 1 + self.assertEqual(slice_consts, expected) + def load(): return x[a:b] + x [a:] + x[:b] + x[:] @@ -1385,15 +1409,30 @@ def long_slice(): def aug(): x[a:b] += y - check_op_count(load, "BINARY_SLICE", 4) + def aug_const(): + x[1:2] += y + + def compound_const_slice(): + x[1:2:3, 4:5:6] = y + + check_op_count(load, "BINARY_SLICE", 3) check_op_count(load, "BUILD_SLICE", 0) - check_op_count(store, "STORE_SLICE", 4) + check_consts(load, slice, 1) + check_op_count(store, "STORE_SLICE", 3) check_op_count(store, "BUILD_SLICE", 0) + check_consts(store, slice, 1) check_op_count(long_slice, "BUILD_SLICE", 1) check_op_count(long_slice, "BINARY_SLICE", 0) check_op_count(aug, "BINARY_SLICE", 1) check_op_count(aug, "STORE_SLICE", 1) check_op_count(aug, "BUILD_SLICE", 0) + check_op_count(aug_const, "BINARY_SLICE", 0) + check_op_count(aug_const, "STORE_SLICE", 0) + check_consts(aug_const, slice, 1) + check_op_count(compound_const_slice, "BINARY_SLICE", 0) + check_op_count(compound_const_slice, "BUILD_SLICE", 0) + check_consts(compound_const_slice, slice, 0) + check_consts(compound_const_slice, tuple, 1) def test_compare_positions(self): for opname_prefix, op in [ @@ -2645,6 +2684,8 @@ def test_return_inside_async_with_block(self): """ self.check_stack_size(snippet, async_=True) +@support.cpython_only +@unittest.skipIf(_testinternalcapi is None, 'need _testinternalcapi module') class TestInstructionSequence(unittest.TestCase): def compare_instructions(self, seq, expected): self.assertEqual([(opcode.opname[i[0]],) + i[1:] for i in seq.get_instructions()], diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index c718ee1203cbe0..ce5c03659f1979 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -1103,6 +1103,12 @@ class mydialect(csv.Dialect): mydialect.quoting = None self.assertRaises(csv.Error, mydialect) + mydialect.quoting = 42 + with self.assertRaises(csv.Error) as cm: + mydialect() + self.assertEqual(str(cm.exception), + 'bad "quoting" value') + mydialect.doublequote = True mydialect.quoting = csv.QUOTE_ALL mydialect.quotechar = '"' diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 83d10dd8579074..cc3aa561cd4c42 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -1081,6 +1081,14 @@ def test_resize_term(self): self.assertEqual(curses.LINES, lines) self.assertEqual(curses.COLS, cols) + with self.assertRaises(OverflowError): + curses.resize_term(35000, 1) + with self.assertRaises(OverflowError): + curses.resize_term(1, 35000) + # GH-120378: Overflow failure in resize_term() causes refresh to fail + tmp = curses.initscr() + tmp.erase() + @requires_curses_func('resizeterm') def test_resizeterm(self): curses.update_lines_cols() @@ -1095,6 +1103,14 @@ def test_resizeterm(self): self.assertEqual(curses.LINES, lines) self.assertEqual(curses.COLS, cols) + with self.assertRaises(OverflowError): + curses.resizeterm(35000, 1) + with self.assertRaises(OverflowError): + curses.resizeterm(1, 35000) + # GH-120378: Overflow failure in resizeterm() causes refresh to fail + tmp = curses.initscr() + tmp.erase() + def test_ungetch(self): curses.ungetch(b'A') self.assertEqual(self.stdscr.getkey(), 'A') diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 2984f4261bd2c4..2e6c49e29ce828 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -4317,6 +4317,23 @@ def test_funny_class_names_names(self): C = make_dataclass(classname, ['a', 'b']) self.assertEqual(C.__name__, classname) + def test_dataclass_decorator_default(self): + C = make_dataclass('C', [('x', int)], decorator=dataclass) + c = C(10) + self.assertEqual(c.x, 10) + + def test_dataclass_custom_decorator(self): + def custom_dataclass(cls, *args, **kwargs): + dc = dataclass(cls, *args, **kwargs) + dc.__custom__ = True + return dc + + C = make_dataclass('C', [('x', int)], decorator=custom_dataclass) + c = C(10) + self.assertEqual(c.x, 10) + self.assertEqual(c.__custom__, True) + + class TestReplace(unittest.TestCase): def test(self): @dataclass(frozen=True) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index c591fd54430b18..d1e7e69e7e951b 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -1253,7 +1253,7 @@ def test_deprecated_N_format(self): self.assertRaises(ValueError, format, h, '10Nf') self.assertRaises(ValueError, format, h, 'Nx') - @run_with_locale('LC_ALL', 'ps_AF') + @run_with_locale('LC_ALL', 'ps_AF', '') def test_wide_char_separator_decimal_point(self): # locale with wide char separator and decimal point Decimal = self.decimal.Decimal diff --git a/Lib/test/test_dict_version.py b/Lib/test/test_dict_version.py deleted file mode 100644 index 243084c75c42bc..00000000000000 --- a/Lib/test/test_dict_version.py +++ /dev/null @@ -1,191 +0,0 @@ -""" -Test implementation of the PEP 509: dictionary versioning. -""" -import unittest -from test.support import import_helper - -# PEP 509 is implemented in CPython but other Python implementations -# don't require to implement it -_testcapi = import_helper.import_module('_testcapi') - - -class DictVersionTests(unittest.TestCase): - type2test = dict - - def setUp(self): - self.seen_versions = set() - self.dict = None - - def check_version_unique(self, mydict): - version = _testcapi.dict_get_version(mydict) - self.assertNotIn(version, self.seen_versions) - self.seen_versions.add(version) - - def check_version_changed(self, mydict, method, *args, **kw): - result = method(*args, **kw) - self.check_version_unique(mydict) - return result - - def check_version_dont_change(self, mydict, method, *args, **kw): - version1 = _testcapi.dict_get_version(mydict) - self.seen_versions.add(version1) - - result = method(*args, **kw) - - version2 = _testcapi.dict_get_version(mydict) - self.assertEqual(version2, version1, "version changed") - - return result - - def new_dict(self, *args, **kw): - d = self.type2test(*args, **kw) - self.check_version_unique(d) - return d - - def test_constructor(self): - # new empty dictionaries must all have an unique version - empty1 = self.new_dict() - empty2 = self.new_dict() - empty3 = self.new_dict() - - # non-empty dictionaries must also have an unique version - nonempty1 = self.new_dict(x='x') - nonempty2 = self.new_dict(x='x', y='y') - - def test_copy(self): - d = self.new_dict(a=1, b=2) - - d2 = self.check_version_dont_change(d, d.copy) - - # dict.copy() must create a dictionary with a new unique version - self.check_version_unique(d2) - - def test_setitem(self): - d = self.new_dict() - - # creating new keys must change the version - self.check_version_changed(d, d.__setitem__, 'x', 'x') - self.check_version_changed(d, d.__setitem__, 'y', 'y') - - # changing values must change the version - self.check_version_changed(d, d.__setitem__, 'x', 1) - self.check_version_changed(d, d.__setitem__, 'y', 2) - - def test_setitem_same_value(self): - value = object() - d = self.new_dict() - - # setting a key must change the version - self.check_version_changed(d, d.__setitem__, 'key', value) - - # setting a key to the same value with dict.__setitem__ - # must change the version - self.check_version_dont_change(d, d.__setitem__, 'key', value) - - # setting a key to the same value with dict.update - # must change the version - self.check_version_dont_change(d, d.update, key=value) - - d2 = self.new_dict(key=value) - self.check_version_dont_change(d, d.update, d2) - - def test_setitem_equal(self): - class AlwaysEqual: - def __eq__(self, other): - return True - - value1 = AlwaysEqual() - value2 = AlwaysEqual() - self.assertTrue(value1 == value2) - self.assertFalse(value1 != value2) - self.assertIsNot(value1, value2) - - d = self.new_dict() - self.check_version_changed(d, d.__setitem__, 'key', value1) - self.assertIs(d['key'], value1) - - # setting a key to a value equal to the current value - # with dict.__setitem__() must change the version - self.check_version_changed(d, d.__setitem__, 'key', value2) - self.assertIs(d['key'], value2) - - # setting a key to a value equal to the current value - # with dict.update() must change the version - self.check_version_changed(d, d.update, key=value1) - self.assertIs(d['key'], value1) - - d2 = self.new_dict(key=value2) - self.check_version_changed(d, d.update, d2) - self.assertIs(d['key'], value2) - - def test_setdefault(self): - d = self.new_dict() - - # setting a key with dict.setdefault() must change the version - self.check_version_changed(d, d.setdefault, 'key', 'value1') - - # don't change the version if the key already exists - self.check_version_dont_change(d, d.setdefault, 'key', 'value2') - - def test_delitem(self): - d = self.new_dict(key='value') - - # deleting a key with dict.__delitem__() must change the version - self.check_version_changed(d, d.__delitem__, 'key') - - # don't change the version if the key doesn't exist - self.check_version_dont_change(d, self.assertRaises, KeyError, - d.__delitem__, 'key') - - def test_pop(self): - d = self.new_dict(key='value') - - # pop() must change the version if the key exists - self.check_version_changed(d, d.pop, 'key') - - # pop() must not change the version if the key does not exist - self.check_version_dont_change(d, self.assertRaises, KeyError, - d.pop, 'key') - - def test_popitem(self): - d = self.new_dict(key='value') - - # popitem() must change the version if the dict is not empty - self.check_version_changed(d, d.popitem) - - # popitem() must not change the version if the dict is empty - self.check_version_dont_change(d, self.assertRaises, KeyError, - d.popitem) - - def test_update(self): - d = self.new_dict(key='value') - - # update() calling with no argument must not change the version - self.check_version_dont_change(d, d.update) - - # update() must change the version - self.check_version_changed(d, d.update, key='new value') - - d2 = self.new_dict(key='value 3') - self.check_version_changed(d, d.update, d2) - - def test_clear(self): - d = self.new_dict(key='value') - - # clear() must change the version if the dict is not empty - self.check_version_changed(d, d.clear) - - # clear() must not change the version if the dict is empty - self.check_version_dont_change(d, d.clear) - - -class Dict(dict): - pass - - -class DictSubtypeVersionTests(DictVersionTests): - type2test = Dict - - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index 3edc19d8254754..035d4418b15c51 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -168,7 +168,8 @@ def run_repeated_init_and_subinterpreters(self): # Parse the line from the loop. The first line is the main # interpreter and the 3 afterward are subinterpreters. interp = Interp(*match.groups()) - if support.verbose > 1: + if support.verbose > 2: + # 5 lines per pass is super-spammy, so limit that to -vvv print(interp) self.assertTrue(interp.interp) self.assertTrue(interp.tstate) @@ -279,6 +280,10 @@ def test_pre_initialization_api(self): """ env = dict(os.environ, PYTHONPATH=os.pathsep.join(sys.path)) out, err = self.run_embedded_interpreter("test_pre_initialization_api", env=env) + if support.verbose > 1: + print() + print(out) + print(err) if MS_WINDOWS: expected_path = self.test_exe else: @@ -296,6 +301,10 @@ def test_pre_initialization_sys_options(self): env['PYTHONPATH'] = os.pathsep.join(sys.path) out, err = self.run_embedded_interpreter( "test_pre_initialization_sys_options", env=env) + if support.verbose > 1: + print() + print(out) + print(err) expected_output = ( "sys.warnoptions: ['once', 'module', 'default']\n" "sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n" diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index ba858c49400911..b3c21cd4f3d585 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -8,6 +8,7 @@ import weakref import errno from codecs import BOM_UTF8 +from itertools import product from textwrap import dedent from test.support import (captured_stderr, check_impl_detail, @@ -1336,6 +1337,29 @@ def test_unicode_errors_no_object(self): for klass in klasses: self.assertEqual(str(klass.__new__(klass)), "") + def test_unicode_error_str_does_not_crash(self): + # Test that str(UnicodeError(...)) does not crash. + # See https://github.com/python/cpython/issues/123378. + + for start, end, objlen in product( + range(-5, 5), + range(-5, 5), + range(7), + ): + obj = 'a' * objlen + with self.subTest('encode', objlen=objlen, start=start, end=end): + exc = UnicodeEncodeError('utf-8', obj, start, end, '') + self.assertIsInstance(str(exc), str) + + with self.subTest('translate', objlen=objlen, start=start, end=end): + exc = UnicodeTranslateError(obj, start, end, '') + self.assertIsInstance(str(exc), str) + + encoded = obj.encode() + with self.subTest('decode', objlen=objlen, start=start, end=end): + exc = UnicodeDecodeError('utf-8', encoded, start, end, '') + self.assertIsInstance(str(exc), str) + @no_tracing def test_badisinstance(self): # Bug #2542: if issubclass(e, MyException) raises an exception, diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 048bb14509064b..f588e16b70123a 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -175,7 +175,7 @@ def check(s): # non-UTF-8 byte string check(b'123\xa0') - @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE') + @support.run_with_locale('LC_NUMERIC', 'fr_FR', 'de_DE', '') def test_float_with_comma(self): # set locale to something that doesn't use '.' for the decimal point # float must not accept the locale specific decimal point but diff --git a/Lib/test/test_free_threading/test_dict.py b/Lib/test/test_free_threading/test_dict.py index 3126458e08e50a..80daf0d9cae9e0 100644 --- a/Lib/test/test_free_threading/test_dict.py +++ b/Lib/test/test_free_threading/test_dict.py @@ -142,41 +142,6 @@ def writer_func(l): for ref in thread_list: self.assertIsNone(ref()) - @unittest.skipIf(_testcapi is None, 'need _testcapi module') - def test_dict_version(self): - dict_version = _testcapi.dict_version - THREAD_COUNT = 10 - DICT_COUNT = 10000 - lists = [] - writers = [] - - def writer_func(thread_list): - for i in range(DICT_COUNT): - thread_list.append(dict_version({})) - - for x in range(THREAD_COUNT): - thread_list = [] - lists.append(thread_list) - writer = Thread(target=partial(writer_func, thread_list)) - writers.append(writer) - - for writer in writers: - writer.start() - - for writer in writers: - writer.join() - - total_len = 0 - values = set() - for thread_list in lists: - for v in thread_list: - if v in values: - print('dup', v, (v/4096)%256) - values.add(v) - total_len += len(thread_list) - versions = set(dict_version for thread_list in lists for dict_version in thread_list) - self.assertEqual(len(versions), THREAD_COUNT*DICT_COUNT) - if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py index b3fc5ad42e7fde..d919d62613ea7c 100644 --- a/Lib/test/test_funcattrs.py +++ b/Lib/test/test_funcattrs.py @@ -98,7 +98,12 @@ def test___globals__(self): (AttributeError, TypeError)) def test___builtins__(self): - self.assertIs(self.b.__builtins__, __builtins__) + if __name__ == "__main__": + builtins_dict = __builtins__.__dict__ + else: + builtins_dict = __builtins__ + + self.assertIs(self.b.__builtins__, builtins_dict) self.cannot_set_attr(self.b, '__builtins__', 2, (AttributeError, TypeError)) @@ -108,7 +113,7 @@ def func(s): return len(s) ns = {} func2 = type(func)(func.__code__, ns) self.assertIs(func2.__globals__, ns) - self.assertIs(func2.__builtins__, __builtins__) + self.assertIs(func2.__builtins__, builtins_dict) # Make sure that the function actually works. self.assertEqual(func2("abc"), 3) diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py index 214e53dde64bbf..5b15838f077f3b 100644 --- a/Lib/test/test_generated_cases.py +++ b/Lib/test/test_generated_cases.py @@ -60,7 +60,7 @@ def test_effect_sizes(self): stack.pop(y) stack.pop(x) for out in outputs: - stack.push(Local.local(out)) + stack.push(Local.undefined(out)) self.assertEqual(stack.base_offset.to_c(), "-1 - oparg - oparg*2") self.assertEqual(stack.top_offset.to_c(), "1 - oparg - oparg*2 + oparg*4") @@ -122,7 +122,7 @@ def run_cases_test(self, input: str, expected: str): def test_inst_no_args(self): input = """ inst(OP, (--)) { - spam(); + SPAM(); } """ output = """ @@ -130,7 +130,7 @@ def test_inst_no_args(self): frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(OP); - spam(); + SPAM(); DISPATCH(); } """ @@ -139,7 +139,8 @@ def test_inst_no_args(self): def test_inst_one_pop(self): input = """ inst(OP, (value --)) { - spam(value); + SPAM(value); + DEAD(value); } """ output = """ @@ -149,7 +150,7 @@ def test_inst_one_pop(self): INSTRUCTION_STATS(OP); _PyStackRef value; value = stack_pointer[-1]; - spam(value); + SPAM(value); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -160,7 +161,7 @@ def test_inst_one_pop(self): def test_inst_one_push(self): input = """ inst(OP, (-- res)) { - res = spam(); + res = SPAM(); } """ output = """ @@ -169,7 +170,7 @@ def test_inst_one_push(self): next_instr += 1; INSTRUCTION_STATS(OP); _PyStackRef res; - res = spam(); + res = SPAM(); stack_pointer[0] = res; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -181,7 +182,8 @@ def test_inst_one_push(self): def test_inst_one_push_one_pop(self): input = """ inst(OP, (value -- res)) { - res = spam(value); + res = SPAM(value); + DEAD(value); } """ output = """ @@ -192,7 +194,7 @@ def test_inst_one_push_one_pop(self): _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; - res = spam(value); + res = SPAM(value); stack_pointer[-1] = res; DISPATCH(); } @@ -202,7 +204,9 @@ def test_inst_one_push_one_pop(self): def test_binary_op(self): input = """ inst(OP, (left, right -- res)) { - res = spam(left, right); + res = SPAM(left, right); + INPUTS_DEAD(); + } """ output = """ @@ -215,7 +219,7 @@ def test_binary_op(self): _PyStackRef res; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = spam(left, right); + res = SPAM(left, right); stack_pointer[-2] = res; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -227,7 +231,8 @@ def test_binary_op(self): def test_overlap(self): input = """ inst(OP, (left, right -- left, result)) { - result = spam(left, right); + result = SPAM(left, right); + INPUTS_DEAD(); } """ output = """ @@ -240,7 +245,7 @@ def test_overlap(self): _PyStackRef result; right = stack_pointer[-1]; left = stack_pointer[-2]; - result = spam(left, right); + result = SPAM(left, right); stack_pointer[-1] = result; DISPATCH(); } @@ -249,7 +254,8 @@ def test_overlap(self): def test_predictions(self): input = """ - inst(OP1, (arg -- rest)) { + inst(OP1, (arg -- res)) { + res = Py_None; } inst(OP3, (arg -- res)) { DEOPT_IF(xxx); @@ -263,7 +269,9 @@ def test_predictions(self): next_instr += 1; INSTRUCTION_STATS(OP1); PREDICTED(OP1); - stack_pointer[-1] = rest; + _PyStackRef res; + res = Py_None; + stack_pointer[-1] = res; DISPATCH(); } @@ -281,6 +289,67 @@ def test_predictions(self): """ self.run_cases_test(input, output) + def test_sync_sp(self): + input = """ + inst(A, (arg -- res)) { + SYNC_SP(); + escaping_call(); + res = Py_None; + } + inst(B, (arg -- res)) { + res = Py_None; + SYNC_SP(); + escaping_call(); + } + """ + output = """ + TARGET(A) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(A); + _PyStackRef res; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + escaping_call(); + stack_pointer = _PyFrame_GetStackPointer(frame); + res = Py_None; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + + TARGET(B) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(B); + _PyStackRef res; + res = Py_None; + stack_pointer[-1] = res; + _PyFrame_SetStackPointer(frame, stack_pointer); + escaping_call(); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + + def test_pep7_condition(self): + input = """ + inst(OP, (arg1 -- out)) { + if (arg1) + out = 0; + else { + out = 1; + } + } + """ + output = "" + with self.assertRaises(SyntaxError): + self.run_cases_test(input, output) + def test_error_if_plain(self): input = """ inst(OP, (--)) { @@ -319,8 +388,10 @@ def test_error_if_plain_with_comment(self): def test_error_if_pop(self): input = """ inst(OP, (left, right -- res)) { - res = spam(left, right); + SPAM(left, right); + INPUTS_DEAD(); ERROR_IF(cond, label); + res = 0; } """ output = """ @@ -333,7 +404,36 @@ def test_error_if_pop(self): _PyStackRef res; right = stack_pointer[-1]; left = stack_pointer[-2]; - res = spam(left, right); + SPAM(left, right); + if (cond) goto pop_2_label; + res = 0; + stack_pointer[-2] = res; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_error_if_pop_with_result(self): + input = """ + inst(OP, (left, right -- res)) { + res = SPAM(left, right); + INPUTS_DEAD(); + ERROR_IF(cond, label); + } + """ + output = """ + TARGET(OP) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(OP); + _PyStackRef left; + _PyStackRef right; + _PyStackRef res; + right = stack_pointer[-1]; + left = stack_pointer[-2]; + res = SPAM(left, right); if (cond) goto pop_2_label; stack_pointer[-2] = res; stack_pointer += -1; @@ -388,10 +488,12 @@ def test_macro_instruction(self): } op(OP2, (extra/2, arg2, left, right -- res)) { res = op2(arg2, left, right); + INPUTS_DEAD(); } macro(OP) = OP1 + cache/2 + OP2; inst(OP3, (unused/5, arg2, left, right -- res)) { res = op3(arg2, left, right); + INPUTS_DEAD(); } family(OP, INLINE_CACHE_ENTRIES_OP) = { OP3 }; """ @@ -408,20 +510,24 @@ def test_macro_instruction(self): _PyStackRef arg2; _PyStackRef res; // _OP1 - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; + _PyFrame_SetStackPointer(frame, stack_pointer); op1(left, right); + stack_pointer = _PyFrame_GetStackPointer(frame); } /* Skip 2 cache entries */ // OP2 - arg2 = stack_pointer[-3]; { + arg2 = stack_pointer[-3]; uint32_t extra = read_u32(&this_instr[4].cache); (void)extra; + _PyFrame_SetStackPointer(frame, stack_pointer); res = op2(arg2, left, right); + stack_pointer = _PyFrame_GetStackPointer(frame); } stack_pointer[-3] = res; stack_pointer += -2; @@ -440,7 +546,9 @@ def test_macro_instruction(self): left = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; + _PyFrame_SetStackPointer(frame, stack_pointer); op1(left, right); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH(); } @@ -457,7 +565,9 @@ def test_macro_instruction(self): right = stack_pointer[-1]; left = stack_pointer[-2]; arg2 = stack_pointer[-3]; + _PyFrame_SetStackPointer(frame, stack_pointer); res = op3(arg2, left, right); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer[-3] = res; stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -469,7 +579,7 @@ def test_macro_instruction(self): def test_unused_caches(self): input = """ inst(OP, (unused/1, unused/2 --)) { - body(); + body; } """ output = """ @@ -479,7 +589,7 @@ def test_unused_caches(self): INSTRUCTION_STATS(OP); /* Skip 1 cache entry */ /* Skip 2 cache entries */ - body(); + body; DISPATCH(); } """ @@ -556,7 +666,7 @@ def test_pseudo_instruction_as_sequence(self): def test_array_input(self): input = """ inst(OP, (below, values[oparg*2], above --)) { - spam(values, oparg); + SPAM(values, oparg); } """ output = """ @@ -566,7 +676,7 @@ def test_array_input(self): INSTRUCTION_STATS(OP); _PyStackRef *values; values = &stack_pointer[-1 - oparg*2]; - spam(values, oparg); + SPAM(values, oparg); stack_pointer += -2 - oparg*2; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -577,7 +687,9 @@ def test_array_input(self): def test_array_output(self): input = """ inst(OP, (unused, unused -- below, values[oparg*3], above)) { - spam(values, oparg); + SPAM(values, oparg); + below = 0; + above = 0; } """ output = """ @@ -585,9 +697,13 @@ def test_array_output(self): frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(OP); + _PyStackRef below; _PyStackRef *values; + _PyStackRef above; values = &stack_pointer[-1]; - spam(values, oparg); + SPAM(values, oparg); + below = 0; + above = 0; stack_pointer[-2] = below; stack_pointer[-1 + oparg*3] = above; stack_pointer += oparg*3; @@ -600,7 +716,8 @@ def test_array_output(self): def test_array_input_output(self): input = """ inst(OP, (values[oparg] -- values[oparg], above)) { - spam(values, oparg); + SPAM(values, oparg); + above = 0; } """ output = """ @@ -609,8 +726,10 @@ def test_array_input_output(self): next_instr += 1; INSTRUCTION_STATS(OP); _PyStackRef *values; + _PyStackRef above; values = &stack_pointer[-oparg]; - spam(values, oparg); + SPAM(values, oparg); + above = 0; stack_pointer[0] = above; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -645,7 +764,10 @@ def test_array_error_if(self): def test_cond_effect(self): input = """ inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) { - output = spam(oparg, aa, cc, input); + output = SPAM(oparg, aa, cc, input); + INPUTS_DEAD(); + xx = 0; + zz = 0; } """ output = """ @@ -656,11 +778,15 @@ def test_cond_effect(self): _PyStackRef aa; _PyStackRef input = PyStackRef_NULL; _PyStackRef cc; + _PyStackRef xx; _PyStackRef output = PyStackRef_NULL; + _PyStackRef zz; cc = stack_pointer[-1]; if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)]; } aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)]; - output = spam(oparg, aa, cc, input); + output = SPAM(oparg, aa, cc, input); + xx = 0; + zz = 0; stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx; if (oparg & 2) stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)] = output; stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0)] = zz; @@ -674,11 +800,14 @@ def test_cond_effect(self): def test_macro_cond_effect(self): input = """ op(A, (left, middle, right --)) { - use(left, middle, right); + USE(left, middle, right); + INPUTS_DEAD(); } op(B, (-- deep, extra if (oparg), res)) { + deep = -1; res = 0; extra = 1; + INPUTS_DEAD(); } macro(M) = A + B; """ @@ -690,17 +819,19 @@ def test_macro_cond_effect(self): _PyStackRef left; _PyStackRef middle; _PyStackRef right; + _PyStackRef deep; _PyStackRef extra = PyStackRef_NULL; _PyStackRef res; // A - right = stack_pointer[-1]; - middle = stack_pointer[-2]; - left = stack_pointer[-3]; { - use(left, middle, right); + right = stack_pointer[-1]; + middle = stack_pointer[-2]; + left = stack_pointer[-3]; + USE(left, middle, right); } // B { + deep = -1; res = 0; extra = 1; } @@ -717,10 +848,10 @@ def test_macro_cond_effect(self): def test_macro_push_push(self): input = """ op(A, (-- val1)) { - val1 = spam(); + val1 = SPAM(); } op(B, (-- val2)) { - val2 = spam(); + val2 = SPAM(); } macro(M) = A + B; """ @@ -733,11 +864,11 @@ def test_macro_push_push(self): _PyStackRef val2; // A { - val1 = spam(); + val1 = SPAM(); } // B { - val2 = spam(); + val2 = SPAM(); } stack_pointer[0] = val1; stack_pointer[1] = val2; @@ -751,10 +882,10 @@ def test_macro_push_push(self): def test_override_inst(self): input = """ inst(OP, (--)) { - spam(); + spam; } override inst(OP, (--)) { - ham(); + ham; } """ output = """ @@ -762,7 +893,7 @@ def test_override_inst(self): frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(OP); - ham(); + ham; DISPATCH(); } """ @@ -771,11 +902,11 @@ def test_override_inst(self): def test_override_op(self): input = """ op(OP, (--)) { - spam(); + spam; } macro(M) = OP; override op(OP, (--)) { - ham(); + ham; } """ output = """ @@ -783,7 +914,7 @@ def test_override_op(self): frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(M); - ham(); + ham; DISPATCH(); } """ @@ -792,7 +923,7 @@ def test_override_op(self): def test_annotated_inst(self): input = """ pure inst(OP, (--)) { - ham(); + ham; } """ output = """ @@ -800,7 +931,7 @@ def test_annotated_inst(self): frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(OP); - ham(); + ham; DISPATCH(); } """ @@ -809,7 +940,7 @@ def test_annotated_inst(self): def test_annotated_op(self): input = """ pure op(OP, (--)) { - spam(); + SPAM(); } macro(M) = OP; """ @@ -818,7 +949,7 @@ def test_annotated_op(self): frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(M); - spam(); + SPAM(); DISPATCH(); } """ @@ -826,7 +957,7 @@ def test_annotated_op(self): input = """ pure register specializing op(OP, (--)) { - spam(); + SPAM(); } macro(M) = OP; """ @@ -840,7 +971,7 @@ def test_deopt_and_exit(self): } """ output = "" - with self.assertRaises(Exception): + with self.assertRaises(SyntaxError): self.run_cases_test(input, output) def test_array_of_one(self): @@ -868,6 +999,7 @@ def test_pointer_to_stackref(self): input = """ inst(OP, (arg: _PyStackRef * -- out)) { out = *arg; + DEAD(arg); } """ output = """ @@ -922,14 +1054,14 @@ def test_unused_named_values(self): def test_used_unused_used(self): input = """ op(FIRST, (w -- w)) { - use(w); + USE(w); } op(SECOND, (x -- x)) { } op(THIRD, (y -- y)) { - use(y); + USE(y); } macro(TEST) = FIRST + SECOND + THIRD; @@ -942,17 +1074,17 @@ def test_used_unused_used(self): _PyStackRef w; _PyStackRef y; // FIRST - w = stack_pointer[-1]; { - use(w); + w = stack_pointer[-1]; + USE(w); } // SECOND { } // THIRD - y = w; { - use(y); + y = w; + USE(y); } DISPATCH(); } @@ -965,11 +1097,11 @@ def test_unused_used_used(self): } op(SECOND, (x -- x)) { - use(x); + USE(x); } op(THIRD, (y -- y)) { - use(y); + USE(y); } macro(TEST) = FIRST + SECOND + THIRD; @@ -985,14 +1117,14 @@ def test_unused_used_used(self): { } // SECOND - x = stack_pointer[-1]; { - use(x); + x = stack_pointer[-1]; + USE(x); } // THIRD - y = x; { - use(y); + y = x; + USE(y); } DISPATCH(); } @@ -1007,7 +1139,8 @@ def test_flush(self): } op(SECOND, (a, b -- )) { - use(a, b); + USE(a, b); + INPUTS_DEAD(); } macro(TEST) = FIRST + flush + SECOND; @@ -1030,10 +1163,8 @@ def test_flush(self): stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); // SECOND - b = stack_pointer[-1]; - a = stack_pointer[-2]; { - use(a, b); + USE(a, b); } stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -1047,14 +1178,16 @@ def test_pop_on_error_peeks(self): input = """ op(FIRST, (x, y -- a, b)) { a = x; + DEAD(x); b = y; + DEAD(y); } op(SECOND, (a, b -- a, b)) { } op(THIRD, (j, k --)) { - j,k; // Mark j and k as used + INPUTS_DEAD(); // Mark j and k as used ERROR_IF(cond, error); } @@ -1069,12 +1202,10 @@ def test_pop_on_error_peeks(self): _PyStackRef y; _PyStackRef a; _PyStackRef b; - _PyStackRef j; - _PyStackRef k; // FIRST - y = stack_pointer[-1]; - x = stack_pointer[-2]; { + y = stack_pointer[-1]; + x = stack_pointer[-2]; a = x; b = y; } @@ -1082,10 +1213,8 @@ def test_pop_on_error_peeks(self): { } // THIRD - k = b; - j = a; { - j,k; // Mark j and k as used + // Mark j and k as used if (cond) goto pop_2_error; } stack_pointer += -2; @@ -1126,7 +1255,8 @@ def test_push_then_error(self): b = 1; if (cond) { stack_pointer[0] = a; - stack_pointer += 1; + stack_pointer[1] = b; + stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); goto error; } @@ -1178,6 +1308,69 @@ def test_array_size_inconsistency(self): with self.assertRaises(SyntaxError): self.run_cases_test(input, output) + def test_stack_save_reload(self): + + input = """ + inst(BALANCED, ( -- )) { + SAVE_STACK(); + RELOAD_STACK(); + } + """ + + output = """ + TARGET(BALANCED) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BALANCED); + _PyFrame_SetStackPointer(frame, stack_pointer); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH(); + } + """ + self.run_cases_test(input, output) + + def test_stack_reload_only(self): + + input = """ + inst(BALANCED, ( -- )) { + RELOAD_STACK(); + } + """ + + output = """ + TARGET(BALANCED) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BALANCED); + _PyFrame_SetStackPointer(frame, stack_pointer); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH(); + } + """ + with self.assertRaises(SyntaxError): + self.run_cases_test(input, output) + + def test_stack_save_only(self): + + input = """ + inst(BALANCED, ( -- )) { + SAVE_STACK(); + } + """ + + output = """ + TARGET(BALANCED) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BALANCED); + _PyFrame_SetStackPointer(frame, stack_pointer); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH(); + } + """ + with self.assertRaises(SyntaxError): + self.run_cases_test(input, output) + class TestGeneratedAbstractCases(unittest.TestCase): def setUp(self) -> None: @@ -1232,7 +1425,7 @@ def run_cases_test(self, input: str, input2: str, expected: str): def test_overridden_abstract(self): input = """ pure op(OP, (--)) { - spam(); + SPAM(); } """ input2 = """ @@ -1251,22 +1444,23 @@ def test_overridden_abstract(self): def test_overridden_abstract_args(self): input = """ pure op(OP, (arg1 -- out)) { - spam(); + out = SPAM(arg1); } op(OP2, (arg1 -- out)) { - eggs(); + out = EGGS(arg1); } """ input2 = """ op(OP, (arg1 -- out)) { - eggs(); + out = EGGS(arg1); } """ output = """ case OP: { _Py_UopsSymbol *arg1; _Py_UopsSymbol *out; - eggs(); + arg1 = stack_pointer[-1]; + out = EGGS(arg1); stack_pointer[-1] = out; break; } @@ -1283,7 +1477,7 @@ def test_overridden_abstract_args(self): def test_no_overridden_case(self): input = """ pure op(OP, (arg1 -- out)) { - spam(); + out = SPAM(arg1); } pure op(OP2, (arg1 -- out)) { @@ -1292,6 +1486,7 @@ def test_no_overridden_case(self): """ input2 = """ pure op(OP2, (arg1 -- out)) { + out = NULL; } """ output = """ @@ -1303,8 +1498,8 @@ def test_no_overridden_case(self): } case OP2: { - _Py_UopsSymbol *arg1; _Py_UopsSymbol *out; + out = NULL; stack_pointer[-1] = out; break; } @@ -1314,7 +1509,7 @@ def test_no_overridden_case(self): def test_missing_override_failure(self): input = """ pure op(OP, (arg1 -- out)) { - spam(); + SPAM(); } """ input2 = """ diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index 1fd75d0a3f4c7b..a6509fc3ba0eae 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -57,7 +57,7 @@ def timevalues(self): timezone(timedelta(0, 2 * 60 * 60))), '"18-May-2033 05:33:20 +0200"'] - @run_with_locale('LC_ALL', 'de_DE', 'fr_FR') + @run_with_locale('LC_ALL', 'de_DE', 'fr_FR', '') # DST rules included to work around quirk where the Gnu C library may not # otherwise restore the previous time zone @run_with_tz('STD-1DST,M3.2.0,M11.1.0') diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 230ba954cd286d..d4ceb7c8dc0b41 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -2377,16 +2377,22 @@ def __getattr__(self, attribute): return getattr(queue, attribute) class CustomQueueFakeProtocol(CustomQueueProtocol): - # An object implementing the Queue API (incorrect signatures). + # An object implementing the minimial Queue API for + # the logging module but with incorrect signatures. + # # The object will be considered a valid queue class since we # do not check the signatures (only callability of methods) # but will NOT be usable in production since a TypeError will - # be raised due to a missing argument. - def empty(self, x): + # be raised due to the extra argument in 'put_nowait'. + def put_nowait(self): pass class CustomQueueWrongProtocol(CustomQueueProtocol): - empty = None + put_nowait = None + +class MinimalQueueProtocol: + def put_nowait(self, x): pass + def get(self): pass def queueMaker(): return queue.Queue() @@ -3946,56 +3952,70 @@ def test_config_queue_handler(self): msg = str(ctx.exception) self.assertEqual(msg, "Unable to configure handler 'ah'") + def _apply_simple_queue_listener_configuration(self, qspec): + self.apply_config({ + "version": 1, + "handlers": { + "queue_listener": { + "class": "logging.handlers.QueueHandler", + "queue": qspec, + }, + }, + }) + @threading_helper.requires_working_threading() @support.requires_subprocess() @patch("multiprocessing.Manager") def test_config_queue_handler_does_not_create_multiprocessing_manager(self, manager): - # gh-120868, gh-121723 - - from multiprocessing import Queue as MQ - - q1 = {"()": "queue.Queue", "maxsize": -1} - q2 = MQ() - q3 = queue.Queue() - # CustomQueueFakeProtocol passes the checks but will not be usable - # since the signatures are incompatible. Checking the Queue API - # without testing the type of the actual queue is a trade-off - # between usability and the work we need to do in order to safely - # check that the queue object correctly implements the API. - q4 = CustomQueueFakeProtocol() - - for qspec in (q1, q2, q3, q4): - self.apply_config( - { - "version": 1, - "handlers": { - "queue_listener": { - "class": "logging.handlers.QueueHandler", - "queue": qspec, - }, - }, - } - ) - manager.assert_not_called() + # gh-120868, gh-121723, gh-124653 + + for qspec in [ + {"()": "queue.Queue", "maxsize": -1}, + queue.Queue(), + # queue.SimpleQueue does not inherit from queue.Queue + queue.SimpleQueue(), + # CustomQueueFakeProtocol passes the checks but will not be usable + # since the signatures are incompatible. Checking the Queue API + # without testing the type of the actual queue is a trade-off + # between usability and the work we need to do in order to safely + # check that the queue object correctly implements the API. + CustomQueueFakeProtocol(), + MinimalQueueProtocol(), + ]: + with self.subTest(qspec=qspec): + self._apply_simple_queue_listener_configuration(qspec) + manager.assert_not_called() @patch("multiprocessing.Manager") def test_config_queue_handler_invalid_config_does_not_create_multiprocessing_manager(self, manager): # gh-120868, gh-121723 for qspec in [object(), CustomQueueWrongProtocol()]: - with self.assertRaises(ValueError): - self.apply_config( - { - "version": 1, - "handlers": { - "queue_listener": { - "class": "logging.handlers.QueueHandler", - "queue": qspec, - }, - }, - } - ) - manager.assert_not_called() + with self.subTest(qspec=qspec), self.assertRaises(ValueError): + self._apply_simple_queue_listener_configuration(qspec) + manager.assert_not_called() + + @skip_if_tsan_fork + @support.requires_subprocess() + @unittest.skipUnless(support.Py_DEBUG, "requires a debug build for testing" + " assertions in multiprocessing") + def test_config_reject_simple_queue_handler_multiprocessing_context(self): + # multiprocessing.SimpleQueue does not implement 'put_nowait' + # and thus cannot be used as a queue-like object (gh-124653) + + import multiprocessing + + if support.MS_WINDOWS: + start_methods = ['spawn'] + else: + start_methods = ['spawn', 'fork', 'forkserver'] + + for start_method in start_methods: + with self.subTest(start_method=start_method): + ctx = multiprocessing.get_context(start_method) + qspec = ctx.SimpleQueue() + with self.assertRaises(ValueError): + self._apply_simple_queue_listener_configuration(qspec) @skip_if_tsan_fork @support.requires_subprocess() diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 351f1067c10343..1b06816214e7d6 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -46,10 +46,14 @@ def nth_line(func, offset): class MonitoringBasicTest(unittest.TestCase): + def tearDown(self): + sys.monitoring.free_tool_id(TEST_TOOL) + def test_has_objects(self): m = sys.monitoring m.events m.use_tool_id + m.clear_tool_id m.free_tool_id m.get_tool m.get_events @@ -77,6 +81,43 @@ def test_tool(self): with self.assertRaises(ValueError): sys.monitoring.set_events(TEST_TOOL, sys.monitoring.events.CALL) + def test_clear(self): + events = [] + sys.monitoring.use_tool_id(TEST_TOOL, "MonitoringTest.Tool") + sys.monitoring.register_callback(TEST_TOOL, E.PY_START, lambda *args: events.append(args)) + sys.monitoring.register_callback(TEST_TOOL, E.LINE, lambda *args: events.append(args)) + def f(): + a = 1 + sys.monitoring.set_local_events(TEST_TOOL, f.__code__, E.LINE) + sys.monitoring.set_events(TEST_TOOL, E.PY_START) + + f() + sys.monitoring.clear_tool_id(TEST_TOOL) + f() + + # the first f() should trigger a PY_START and a LINE event + # the second f() after clear_tool_id should not trigger any event + # the callback function should be cleared as well + self.assertEqual(len(events), 2) + callback = sys.monitoring.register_callback(TEST_TOOL, E.LINE, None) + self.assertIs(callback, None) + + sys.monitoring.free_tool_id(TEST_TOOL) + + events = [] + sys.monitoring.use_tool_id(TEST_TOOL, "MonitoringTest.Tool") + sys.monitoring.register_callback(TEST_TOOL, E.LINE, lambda *args: events.append(args)) + sys.monitoring.set_local_events(TEST_TOOL, f.__code__, E.LINE) + f() + sys.monitoring.free_tool_id(TEST_TOOL) + sys.monitoring.use_tool_id(TEST_TOOL, "MonitoringTest.Tool") + f() + # the first f() should trigger a LINE event, and even if we use the + # tool id immediately after freeing it, the second f() should not + # trigger any event + self.assertEqual(len(events), 1) + sys.monitoring.free_tool_id(TEST_TOOL) + class MonitoringTestBase: @@ -744,8 +785,6 @@ def get_events(self, func, tool, recorders): def check_events(self, func, expected, tool=TEST_TOOL, recorders=(ExceptionRecorder,)): events = self.get_events(func, tool, recorders) - if events != expected: - print(events, file = sys.stderr) self.assertEqual(events, expected) def check_balanced(self, func, recorders): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 4c64a800cb32d2..46eb00261042bc 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -518,6 +518,43 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): (Pdb) continue """ +def test_pdb_break_anywhere(): + """Test break_anywhere() method of Pdb. + + >>> def outer(): + ... def inner(): + ... import pdb + ... import sys + ... p = pdb.Pdb(nosigint=True, readrc=False) + ... p.set_trace() + ... frame = sys._getframe() + ... print(p.break_anywhere(frame)) # inner + ... print(p.break_anywhere(frame.f_back)) # outer + ... print(p.break_anywhere(frame.f_back.f_back)) # caller + ... inner() + + >>> def caller(): + ... outer() + + >>> def test_function(): + ... caller() + + >>> reset_Breakpoint() + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'b 3', + ... 'c', + ... ]): + ... test_function() + > (6)inner() + -> p.set_trace() + (Pdb) b 3 + Breakpoint 1 at :3 + (Pdb) c + True + False + False + """ + def test_pdb_pp_repr_exc(): """Test that do_p/do_pp do not swallow exceptions. diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index 672851425ffb53..b55d441759eb69 100644 --- a/Lib/test/test_perf_profiler.py +++ b/Lib/test/test_perf_profiler.py @@ -23,15 +23,6 @@ raise unittest.SkipTest("test crash randomly on ASAN/MSAN/UBSAN build") -def is_jit_build(): - cflags = (sysconfig.get_config_var("PY_CORE_CFLAGS") or '') - return "_Py_JIT" in cflags - - -if is_jit_build(): - raise unittest.SkipTest("Perf support is not available in JIT builds") - - def supports_trampoline_profiling(): perf_trampoline = sysconfig.get_config_var("PY_HAVE_PERF_TRAMPOLINE") if not perf_trampoline: @@ -71,11 +62,13 @@ def baz(): """ with temp_dir() as script_dir: script = make_script(script_dir, "perftest", code) + env = {**os.environ, "PYTHON_JIT": "0"} with subprocess.Popen( [sys.executable, "-Xperf", script], text=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, + env=env, ) as process: stdout, stderr = process.communicate() @@ -139,11 +132,13 @@ def baz(): """ with temp_dir() as script_dir: script = make_script(script_dir, "perftest", code) + env = {**os.environ, "PYTHON_JIT": "0"} with subprocess.Popen( [sys.executable, "-Xperf", script], text=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, + env=env, ) as process: stdout, stderr = process.communicate() @@ -188,11 +183,13 @@ def baz(): """ with temp_dir() as script_dir: script = make_script(script_dir, "perftest", code) + env = {**os.environ, "PYTHON_JIT": "0"} with subprocess.Popen( [sys.executable, script], text=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, + env=env, ) as process: stdout, stderr = process.communicate() @@ -269,8 +266,9 @@ def perf_command_works(): "-c", 'print("hello")', ) + env = {**os.environ, "PYTHON_JIT": "0"} stdout = subprocess.check_output( - cmd, cwd=script_dir, text=True, stderr=subprocess.STDOUT + cmd, cwd=script_dir, text=True, stderr=subprocess.STDOUT, env=env ) except (subprocess.SubprocessError, OSError): return False @@ -282,11 +280,10 @@ def perf_command_works(): def run_perf(cwd, *args, use_jit=False, **env_vars): + env = os.environ.copy() if env_vars: - env = os.environ.copy() env.update(env_vars) - else: - env = None + env["PYTHON_JIT"] = "0" output_file = cwd + "/perf_output.perf" if not use_jit: base_cmd = ("perf", "record", "-g", "--call-graph=fp", "-o", output_file, "--") @@ -455,11 +452,13 @@ def compile_trampolines_for_all_functions(): with temp_dir() as script_dir: script = make_script(script_dir, "perftest", code) + env = {**os.environ, "PYTHON_JIT": "0"} with subprocess.Popen( [sys.executable, "-Xperf", script], universal_newlines=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE, + env=env, ) as process: stdout, stderr = process.communicate() diff --git a/Lib/test/test_pyrepl/test_pyrepl.py b/Lib/test/test_pyrepl/test_pyrepl.py index 36f940eaea4eac..1a76832386bf1d 100644 --- a/Lib/test/test_pyrepl/test_pyrepl.py +++ b/Lib/test/test_pyrepl/test_pyrepl.py @@ -1204,6 +1204,18 @@ def test_python_basic_repl(self): self.assertNotIn("Exception", output) self.assertNotIn("Traceback", output) + # The site module must not load _pyrepl if PYTHON_BASIC_REPL is set + commands = ("import sys\n" + "print('_pyrepl' in sys.modules)\n" + "exit()\n") + env["PYTHON_BASIC_REPL"] = "1" + output, exit_code = self.run_repl(commands, env=env) + self.assertEqual(exit_code, 0) + self.assertIn("False", output) + self.assertNotIn("True", output) + self.assertNotIn("Exception", output) + self.assertNotIn("Traceback", output) + @force_not_colorized def test_bad_sys_excepthook_doesnt_crash_pyrepl(self): env = os.environ.copy() diff --git a/Lib/test/test_repl.py b/Lib/test/test_repl.py index 7a7285a1a2fcfd..e764e60560db23 100644 --- a/Lib/test/test_repl.py +++ b/Lib/test/test_repl.py @@ -291,5 +291,42 @@ def f(): self.assertEqual(traceback_lines, expected_lines) +class TestAsyncioREPLContextVars(unittest.TestCase): + def test_toplevel_contextvars_sync(self): + user_input = dedent("""\ + from contextvars import ContextVar + var = ContextVar("var", default="failed") + var.set("ok") + """) + p = spawn_repl("-m", "asyncio") + p.stdin.write(user_input) + user_input2 = dedent(""" + print(f"toplevel contextvar test: {var.get()}") + """) + p.stdin.write(user_input2) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + expected = "toplevel contextvar test: ok" + self.assertIn(expected, output, expected) + + def test_toplevel_contextvars_async(self): + user_input = dedent("""\ + from contextvars import ContextVar + var = ContextVar('var', default='failed') + """) + p = spawn_repl("-m", "asyncio") + p.stdin.write(user_input) + user_input2 = "async def set_var(): var.set('ok')\n" + p.stdin.write(user_input2) + user_input3 = "await set_var()\n" + p.stdin.write(user_input3) + user_input4 = "print(f'toplevel contextvar test: {var.get()}')\n" + p.stdin.write(user_input4) + output = kill_python(p) + self.assertEqual(p.returncode, 0) + expected = "toplevel contextvar test: ok" + self.assertIn(expected, output, expected) + + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_stable_abi_ctypes.py b/Lib/test/test_stable_abi_ctypes.py index d16ad7ef5d4328..b14d500a9c6e97 100644 --- a/Lib/test/test_stable_abi_ctypes.py +++ b/Lib/test/test_stable_abi_ctypes.py @@ -805,6 +805,7 @@ def test_windows_feature_macros(self): "PyUnicode_DecodeUnicodeEscape", "PyUnicode_EncodeFSDefault", "PyUnicode_EncodeLocale", + "PyUnicode_Equal", "PyUnicode_EqualToUTF8", "PyUnicode_EqualToUTF8AndSize", "PyUnicode_FSConverter", diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py index 6600dcf9157971..4de6c1cba152bd 100644 --- a/Lib/test/test_str.py +++ b/Lib/test/test_str.py @@ -1665,7 +1665,7 @@ def test_startswith_endswith_errors(self): self.assertIn('str', exc) self.assertIn('tuple', exc) - @support.run_with_locale('LC_ALL', 'de_DE', 'fr_FR') + @support.run_with_locale('LC_ALL', 'de_DE', 'fr_FR', '') def test_format_float(self): # should not format with a comma, but always with C locale self.assertEqual('1.0', '%.1f' % 1.0) diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 038746e26c24ad..37f6b08db28b3e 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -7,7 +7,8 @@ import os import sys from test import support -from test.support import skip_if_buggy_ucrt_strfptime, warnings_helper +from test.support import warnings_helper +from test.support import skip_if_buggy_ucrt_strfptime, run_with_locales from datetime import date as datetime_date import _strptime @@ -207,8 +208,8 @@ class StrptimeTests(unittest.TestCase): """Tests for _strptime.strptime.""" def setUp(self): - """Create testing time tuple.""" - self.time_tuple = time.gmtime() + """Create testing time tuples.""" + self.time_tuple = time.localtime() def test_ValueError(self): # Make sure ValueError is raised when match fails or format is bad @@ -289,54 +290,67 @@ def test_unconverteddata(self): # Check ValueError is raised when there is unconverted data self.assertRaises(ValueError, _strptime._strptime_time, "10 12", "%m") - def helper(self, directive, position): + def roundtrip(self, fmt, position, time_tuple=None): """Helper fxn in testing.""" - fmt = "%d %Y" if directive == 'd' else "%" + directive - strf_output = time.strftime(fmt, self.time_tuple) + if time_tuple is None: + time_tuple = self.time_tuple + strf_output = time.strftime(fmt, time_tuple) strp_output = _strptime._strptime_time(strf_output, fmt) - self.assertTrue(strp_output[position] == self.time_tuple[position], - "testing of '%s' directive failed; '%s' -> %s != %s" % - (directive, strf_output, strp_output[position], - self.time_tuple[position])) + self.assertEqual(strp_output[position], time_tuple[position], + "testing of %r format failed; %r -> %r != %r" % + (fmt, strf_output, strp_output[position], + time_tuple[position])) + if support.verbose >= 3: + print("testing of %r format: %r -> %r" % + (fmt, strf_output, strp_output[position])) def test_year(self): # Test that the year is handled properly - for directive in ('y', 'Y'): - self.helper(directive, 0) + self.roundtrip('%Y', 0) + self.roundtrip('%y', 0) + self.roundtrip('%Y', 0, (1900, 1, 1, 0, 0, 0, 0, 1, 0)) + # Must also make sure %y values are correct for bounds set by Open Group - for century, bounds in ((1900, ('69', '99')), (2000, ('00', '68'))): - for bound in bounds: - strp_output = _strptime._strptime_time(bound, '%y') - expected_result = century + int(bound) - self.assertTrue(strp_output[0] == expected_result, - "'y' test failed; passed in '%s' " - "and returned '%s'" % (bound, strp_output[0])) + strptime = _strptime._strptime_time + self.assertEqual(strptime('00', '%y')[0], 2000) + self.assertEqual(strptime('68', '%y')[0], 2068) + self.assertEqual(strptime('69', '%y')[0], 1969) + self.assertEqual(strptime('99', '%y')[0], 1999) def test_month(self): # Test for month directives - for directive in ('B', 'b', 'm'): - self.helper(directive, 1) + self.roundtrip('%m', 1) + + @run_with_locales('LC_TIME', 'C', 'en_US', 'fr_FR', 'de_DE', 'ja_JP', 'he_IL', '') + def test_month_locale(self): + # Test for month directives + self.roundtrip('%B', 1) + self.roundtrip('%b', 1) + for m in range(1, 13): + self.roundtrip('%B', 1, (1900, m, 1, 0, 0, 0, 0, 1, 0)) + self.roundtrip('%b', 1, (1900, m, 1, 0, 0, 0, 0, 1, 0)) def test_day(self): # Test for day directives - self.helper('d', 2) + self.roundtrip('%d %Y', 2) def test_hour(self): # Test hour directives - self.helper('H', 3) - strf_output = time.strftime("%I %p", self.time_tuple) - strp_output = _strptime._strptime_time(strf_output, "%I %p") - self.assertTrue(strp_output[3] == self.time_tuple[3], - "testing of '%%I %%p' directive failed; '%s' -> %s != %s" % - (strf_output, strp_output[3], self.time_tuple[3])) + self.roundtrip('%H', 3) + + # NB: Only works on locales with AM/PM + @run_with_locales('LC_TIME', 'C', 'en_US', 'ja_JP') + def test_hour_locale(self): + # Test hour directives + self.roundtrip('%I %p', 3) def test_minute(self): # Test minute directives - self.helper('M', 4) + self.roundtrip('%M', 4) def test_second(self): # Test second directives - self.helper('S', 5) + self.roundtrip('%S', 5) def test_fraction(self): # Test microseconds @@ -347,12 +361,18 @@ def test_fraction(self): def test_weekday(self): # Test weekday directives - for directive in ('A', 'a', 'w', 'u'): - self.helper(directive,6) + self.roundtrip('%w', 6) + self.roundtrip('%u', 6) + + @run_with_locales('LC_TIME', 'C', 'en_US', 'fr_FR', 'de_DE', 'ja_JP', '') + def test_weekday_locale(self): + # Test weekday directives + self.roundtrip('%A', 6) + self.roundtrip('%a', 6) def test_julian(self): # Test julian directives - self.helper('j', 7) + self.roundtrip('%j', 7) def test_offset(self): one_hour = 60 * 60 @@ -449,20 +469,96 @@ def test_bad_timezone(self): "time.daylight set to %s and passing in %s" % (time.tzname, tz_value, time.daylight, tz_name)) - def test_date_time(self): + # NB: Does not roundtrip in some locales due to the ambiguity of + # the date and time representation (bugs in locales?): + # * Seconds are not included: bem_ZM, bokmal, ff_SN, nb_NO, nn_NO, + # no_NO, norwegian, nynorsk. + # * Hours are in 12-hour notation without AM/PM indication: hy_AM, + # id_ID, ms_MY. + # * Year is not included: ha_NG. + # * Use non-Gregorian calendar: lo_LA, thai, th_TH. + # + # BUG: Generates invalid regexp for br_FR, csb_PL, Arabic. + # BUG: Generates regexp that does not match the current date and time + # for fa_IR, gez_ER, gez_ET, lzh_TW, my_MM, or_IN, shn_MM, yo_NG. + # BUG: Generates regexp that does not match the current date and time + # for fa_IR, gez_ER, gez_ET, lzh_TW, my_MM, or_IN, shn_MM, yo_NG, + # fr_FR, ja_JP, he_IL, ko_KR, zh_CN, etc. + @run_with_locales('LC_TIME', 'C', 'en_US', 'de_DE', + 'eu_ES', 'mfe_MU') + def test_date_time_locale(self): # Test %c directive - for position in range(6): - self.helper('c', position) - - def test_date(self): + now = time.time() + self.roundtrip('%c', slice(0, 6), time.localtime(now)) + # 1 hour 20 minutes 30 seconds ago + self.roundtrip('%c', slice(0, 6), time.localtime(now - 4830)) + # 12 hours ago + self.roundtrip('%c', slice(0, 6), time.localtime(now - 12*3600)) + # different days of the week + for i in range(1, 7): + self.roundtrip('%c', slice(0, 6), time.localtime(now - i*24*3600)) + # different months + for i in range(1, 12): + self.roundtrip('%c', slice(0, 6), time.localtime(now - i*30*24*3600)) + # different year + self.roundtrip('%c', slice(0, 6), time.localtime(now - 366*24*3600)) + + # NB: Dates before 1969 do not roundtrip on some locales: + # bo_CN, bo_IN, dz_BT, eu_ES, eu_FR. + @run_with_locales('LC_TIME', 'C', 'en_US', 'de_DE', 'ja_JP') + def test_date_time_locale2(self): + # Test %c directive + self.roundtrip('%c', slice(0, 6), (1900, 1, 1, 0, 0, 0, 0, 1, 0)) + + # NB: Does not roundtrip because use non-Gregorian calendar: + # lo_LA, thai, th_TH. + # BUG: Generates regexp that does not match the current date + # for az_IR, fa_IR, lzh_TW, my_MM, or_IN, shn_MM, + # Arabic, ja_JP, ko_KR, zh_CN, etc. + @run_with_locales('LC_TIME', 'C', 'en_US', 'fr_FR', 'de_DE', + 'he_IL', 'eu_ES') + def test_date_locale(self): # Test %x directive - for position in range(0,3): - self.helper('x', position) - - def test_time(self): + now = time.time() + self.roundtrip('%x', slice(0, 3), time.localtime(now)) + # different days of the week + for i in range(1, 7): + self.roundtrip('%x', slice(0, 3), time.localtime(now - i*24*3600)) + # different months + for i in range(1, 12): + self.roundtrip('%x', slice(0, 3), time.localtime(now - i*30*24*3600)) + # different year + self.roundtrip('%x', slice(0, 3), time.localtime(now - 366*24*3600)) + + # NB: Dates before 1969 do not roundtrip on many locales, including C. + @unittest.skipIf( + support.is_emscripten or support.is_wasi, + "musl libc issue on Emscripten, bpo-46390" + ) + @run_with_locales('LC_TIME', 'en_US', 'fr_FR', 'de_DE', 'ja_JP') + def test_date_locale2(self): + # Test %x directive + self.roundtrip('%x', slice(0, 3), (1900, 1, 1, 0, 0, 0, 0, 1, 0)) + + # NB: Does not roundtrip in some locales due to the ambiguity of + # the time representation (bugs in locales?): + # * Seconds are not included: bokmal, ff_SN, nb_NO, nn_NO, no_NO, + # norwegian, nynorsk. + # * Hours are in 12-hour notation without AM/PM indication: hy_AM, + # ms_MY, sm_WS. + # BUG: Generates regexp that does not match the current time for + # aa_DJ, aa_ER, aa_ET, am_ET, az_IR, byn_ER, fa_IR, gez_ER, gez_ET, + # lzh_TW, my_MM, om_ET, om_KE, or_IN, shn_MM, sid_ET, so_DJ, so_ET, + # so_SO, ti_ER, ti_ET, tig_ER, wal_ET. + @run_with_locales('LC_TIME', 'C', 'en_US', 'fr_FR', 'de_DE', 'ja_JP') + def test_time_locale(self): # Test %X directive - for position in range(3,6): - self.helper('X', position) + now = time.time() + self.roundtrip('%X', slice(3, 6), time.localtime(now)) + # 1 hour 20 minutes 30 seconds ago + self.roundtrip('%X', slice(3, 6), time.localtime(now - 4830)) + # 12 hours ago + self.roundtrip('%X', slice(3, 6), time.localtime(now - 12*3600)) def test_percent(self): # Make sure % signs are handled properly @@ -714,12 +810,7 @@ def test_new_localetime(self): def test_TimeRE_recreation_locale(self): # The TimeRE instance should be recreated upon changing the locale. - locale_info = locale.getlocale(locale.LC_TIME) - try: - locale.setlocale(locale.LC_TIME, ('en_US', 'UTF8')) - except locale.Error: - self.skipTest('test needs en_US.UTF8 locale') - try: + with support.run_with_locale('LC_TIME', 'en_US.UTF8'): _strptime._strptime_time('10 2004', '%d %Y') # Get id of current cache object. first_time_re = _strptime._TimeRE_cache @@ -736,10 +827,6 @@ def test_TimeRE_recreation_locale(self): # to the resetting to the original locale. except locale.Error: self.skipTest('test needs de_DE.UTF8 locale') - # Make sure we don't trample on the locale setting once we leave the - # test. - finally: - locale.setlocale(locale.LC_TIME, locale_info) @support.run_with_tz('STD-1DST,M4.1.0,M10.1.0') def test_TimeRE_recreation_timezone(self): diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py index bdbf8800cfd8f6..e3193c7863fbae 100644 --- a/Lib/test/test_struct.py +++ b/Lib/test/test_struct.py @@ -1,4 +1,5 @@ from collections import abc +from itertools import combinations import array import gc import math @@ -11,12 +12,22 @@ from test import support from test.support import import_helper, suppress_immortalization from test.support.script_helper import assert_python_ok +from test.support.testcase import ComplexesAreIdenticalMixin ISBIGENDIAN = sys.byteorder == "big" integer_codes = 'b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q', 'n', 'N' byteorders = '', '@', '=', '<', '>', '!' +INF = float('inf') +NAN = float('nan') + +try: + struct.pack('C', 1j) + have_c_complex = True +except struct.error: + have_c_complex = False + def iter_integer_formats(byteorders=byteorders): for code in integer_codes: for byteorder in byteorders: @@ -33,7 +44,7 @@ def bigendian_to_native(value): else: return string_reverse(value) -class StructTest(unittest.TestCase): +class StructTest(ComplexesAreIdenticalMixin, unittest.TestCase): def test_isbigendian(self): self.assertEqual((struct.pack('=i', 1)[0] == 0), ISBIGENDIAN) @@ -783,6 +794,30 @@ def test_repr(self): s = struct.Struct('=i2H') self.assertEqual(repr(s), f'Struct({s.format!r})') + @unittest.skipUnless(have_c_complex, "requires C11 complex type support") + def test_c_complex_round_trip(self): + values = [complex(*_) for _ in combinations([1, -1, 0.0, -0.0, 2, + -3, INF, -INF, NAN], 2)] + for z in values: + for f in ['E', 'C', '>E', '>C', ' dict[str, Any]: # n # The spec allows converting "\r\n" to "\n", even in string # literals. Let's do so to simplify parsing. - src = s.replace("\r\n", "\n") + try: + src = s.replace("\r\n", "\n") + except (AttributeError, TypeError): + raise TypeError( + f"Expected str object, not '{type(s).__qualname__}'" + ) from None pos = 0 out = Output(NestedDict(), Flags()) header: Key = () diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py index 028e9483196694..a5cb2bdb064692 100644 --- a/Lib/venv/__init__.py +++ b/Lib/venv/__init__.py @@ -303,8 +303,11 @@ def setup_python(self, context): copier(context.executable, path) if not os.path.islink(path): os.chmod(path, 0o755) - for suffix in ('python', 'python3', - f'python3.{sys.version_info[1]}'): + + suffixes = ['python', 'python3', f'python3.{sys.version_info[1]}'] + if sys.version_info[:2] == (3, 14): + suffixes.append('python𝜋') + for suffix in suffixes: path = os.path.join(binpath, suffix) if not os.path.exists(path): # Issue 18807: make copies if diff --git a/Makefile.pre.in b/Makefile.pre.in index a4d99262702a17..07c8a4d20142db 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -490,7 +490,7 @@ PYTHON_OBJS= \ Python/thread.o \ Python/traceback.o \ Python/tracemalloc.o \ - Python/typeid.o \ + Python/uniqueid.o \ Python/getopt.o \ Python/pystrcmp.o \ Python/pystrtod.o \ @@ -1279,7 +1279,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_tracemalloc.h \ $(srcdir)/Include/internal/pycore_tstate.h \ $(srcdir)/Include/internal/pycore_tuple.h \ - $(srcdir)/Include/internal/pycore_typeid.h \ + $(srcdir)/Include/internal/pycore_uniqueid.h \ $(srcdir)/Include/internal/pycore_typeobject.h \ $(srcdir)/Include/internal/pycore_typevarobject.h \ $(srcdir)/Include/internal/pycore_ucnhash.h \ diff --git a/Misc/NEWS.d/next/C API/2018-06-30-21-48-16.bpo-34008.2Wjtm0.rst b/Misc/NEWS.d/next/C API/2018-06-30-21-48-16.bpo-34008.2Wjtm0.rst new file mode 100644 index 00000000000000..1a01dafc758004 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2018-06-30-21-48-16.bpo-34008.2Wjtm0.rst @@ -0,0 +1,2 @@ +Added ``Py_IsInitialized`` to the list of APIs that are safe to call before +the interpreter is initialized, and updated the embedding tests to cover it. diff --git a/Misc/NEWS.d/next/C API/2022-08-05-19-41-20.gh-issue-87135.SCNBYj.rst b/Misc/NEWS.d/next/C API/2022-08-05-19-41-20.gh-issue-87135.SCNBYj.rst new file mode 100644 index 00000000000000..6387d69bc267c6 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2022-08-05-19-41-20.gh-issue-87135.SCNBYj.rst @@ -0,0 +1,15 @@ +Attempting to acquire the GIL after runtime finalization has begun in a +different thread now causes the thread to hang rather than terminate, which +avoids potential crashes or memory corruption caused by attempting to +terminate a thread that is running code not specifically designed to support +termination. In most cases this hanging is harmless since the process will +soon exit anyway. + +The ``PyThread_exit_thread`` function is now deprecated. Its behavior is +inconsistent across platforms, and it can only be used safely in the +unlikely case that every function in the entire call stack has been designed +to support the platform-dependent termination mechanism. It is recommended +that users of this function change their design to not require thread +termination. In the unlikely case that thread termination is needed and can +be done safely, users may migrate to calling platform-specific APIs such as +``pthread_exit`` (POSIX) or ``_endthreadex`` (Windows) directly. diff --git a/Misc/NEWS.d/next/C_API/2024-09-24-20-34-21.gh-issue-124296.S4QoS1.rst b/Misc/NEWS.d/next/C_API/2024-09-24-20-34-21.gh-issue-124296.S4QoS1.rst new file mode 100644 index 00000000000000..e7b9187655eb31 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2024-09-24-20-34-21.gh-issue-124296.S4QoS1.rst @@ -0,0 +1,3 @@ +:c:type:`PyDictObject` no longer maintains a private version tag field +``ma_version_tag`` per :pep:`699`. This field was originally added in +Python 3.6 (:pep:`509`) and deprecated in Python 3.12. diff --git a/Misc/NEWS.d/next/C_API/2024-09-25-11-44-02.gh-issue-124502.qWuDjT.rst b/Misc/NEWS.d/next/C_API/2024-09-25-11-44-02.gh-issue-124502.qWuDjT.rst new file mode 100644 index 00000000000000..f515619328b359 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2024-09-25-11-44-02.gh-issue-124502.qWuDjT.rst @@ -0,0 +1,2 @@ +Add :c:func:`PyUnicode_Equal` function to the limited C API: test if two +strings are equal. Patch by Victor Stinner. diff --git a/Misc/NEWS.d/next/C_API/2024-10-03-14-06-08.gh-issue-123961.uwJQTY.rst b/Misc/NEWS.d/next/C_API/2024-10-03-14-06-08.gh-issue-123961.uwJQTY.rst new file mode 100644 index 00000000000000..40c26e15a2de92 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2024-10-03-14-06-08.gh-issue-123961.uwJQTY.rst @@ -0,0 +1,3 @@ +Convert the :ref:`curses.window ` static type exposed +by the :c:macro:`!PyCursesWindow_Type` macro in ``Include/py_curses.h`` to a +:ref:`heap type `. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-10-03-22-26-39.gh-issue-124871.tAMF47.rst b/Misc/NEWS.d/next/Core and Builtins/2024-10-03-22-26-39.gh-issue-124871.tAMF47.rst new file mode 100644 index 00000000000000..185cb3048fadf5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-10-03-22-26-39.gh-issue-124871.tAMF47.rst @@ -0,0 +1,2 @@ +Fix compiler bug (in some versions of 3.13) where an assertion fails during reachability +analysis. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-19-16-57-34.gh-issue-119726.DseseK.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-19-16-57-34.gh-issue-119726.DseseK.rst new file mode 100644 index 00000000000000..c01eeff952534f --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-19-16-57-34.gh-issue-119726.DseseK.rst @@ -0,0 +1,2 @@ +The JIT now generates more efficient code for calls to C functions resulting +in up to 0.8% memory savings and 1.5% speed improvement on AArch64. Patch by Diego Russo. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst deleted file mode 100644 index e3741321006548..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-26-18-21-06.gh-issue-116510.FacUWO.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fix a crash caused by immortal interned strings being shared between -sub-interpreters that use basic single-phase init. In that case, the string -can be used by an interpreter that outlives the interpreter that created and -interned it. For interpreters that share obmalloc state, also share the -interned dict with the main interpreter. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-09-30-16-39-37.gh-issue-118093.J2A3gz.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-30-16-39-37.gh-issue-118093.J2A3gz.rst new file mode 100644 index 00000000000000..2e5c64581b6aef --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-09-30-16-39-37.gh-issue-118093.J2A3gz.rst @@ -0,0 +1,2 @@ +Improve the experimental JIT compiler's ability to stay "on trace" when +encountering highly-biased branches. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-10-03-14-39-41.gh-issue-123378.dCxANf.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-03-14-39-41.gh-issue-123378.dCxANf.rst new file mode 100644 index 00000000000000..5cd34535d674d3 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-03-14-39-41.gh-issue-123378.dCxANf.rst @@ -0,0 +1,3 @@ +Fix a crash in the :meth:`~object.__str__` method of :exc:`UnicodeError` +objects when the :attr:`UnicodeError.start` and :attr:`UnicodeError.end` +values are invalid or out-of-range. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-10-05-23-53-06.gh-issue-125008.ETANpd.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-05-23-53-06.gh-issue-125008.ETANpd.rst new file mode 100644 index 00000000000000..8971e052860225 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-10-05-23-53-06.gh-issue-125008.ETANpd.rst @@ -0,0 +1,2 @@ +Fix :func:`tokenize.untokenize` producing invalid syntax for +double braces preceded by certain escape characters. diff --git a/Misc/NEWS.d/next/Documentation/2018-07-04-20-35-25.bpo-34008.bqecIb.rst b/Misc/NEWS.d/next/Documentation/2018-07-04-20-35-25.bpo-34008.bqecIb.rst new file mode 100644 index 00000000000000..a89086af35bfc1 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-07-04-20-35-25.bpo-34008.bqecIb.rst @@ -0,0 +1,8 @@ +The :c:func:`Py_Main` documentation moved from the "Very High Level API" section to the +"Initialization and Finalization" section. + +Also make it explicit that we expect ``Py_Main`` to typically be called instead +of ``Py_Initialize`` rather than after it (since ``Py_Main`` makes its own +call to ``Py_Initialize``). Document that calling both is +supported but is version dependent on which settings +will be applied correctly. diff --git a/Misc/NEWS.d/next/Documentation/2024-08-01-17-18-21.gh-issue-70870.fZnBM9.rst b/Misc/NEWS.d/next/Documentation/2024-08-01-17-18-21.gh-issue-70870.fZnBM9.rst new file mode 100644 index 00000000000000..ba607bf7a42cd9 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2024-08-01-17-18-21.gh-issue-70870.fZnBM9.rst @@ -0,0 +1,3 @@ +Clarified the dual usage of the term "free variable" (both the formal +meaning of any reference to names defined outside the local scope, and the +narrower pragmatic meaning of nonlocal variables named in ``co_freevars``). diff --git a/Misc/NEWS.d/next/Documentation/2024-10-07-00-31-17.gh-issue-125018.yKnymn.rst b/Misc/NEWS.d/next/Documentation/2024-10-07-00-31-17.gh-issue-125018.yKnymn.rst new file mode 100644 index 00000000000000..e910da5b879ba5 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2024-10-07-00-31-17.gh-issue-125018.yKnymn.rst @@ -0,0 +1,4 @@ +The :mod:`importlib.metadata` documentation now includes semantic +cross-reference targets for the significant documented APIs. This means +intersphinx references like :func:`importlib.metadata.version` will +now work as expected. diff --git a/Misc/NEWS.d/next/IDLE/2024-10-04-15-34-34.gh-issue-122392.V8K3w2.rst b/Misc/NEWS.d/next/IDLE/2024-10-04-15-34-34.gh-issue-122392.V8K3w2.rst new file mode 100644 index 00000000000000..541f6212794ef2 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2024-10-04-15-34-34.gh-issue-122392.V8K3w2.rst @@ -0,0 +1,2 @@ +Increase currently inadequate vertical spacing for the IDLE browsers (path, +module, and stack) on high-resolution monitors. diff --git a/Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst b/Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst new file mode 100644 index 00000000000000..221c8e05fa98aa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-12-04-07-36-27.bpo-14074.fMLKCu.rst @@ -0,0 +1,2 @@ +Fix :mod:`argparse` metavar processing to allow positional arguments to have a +tuple metavar. diff --git a/Misc/NEWS.d/next/Library/2024-07-10-08-13-34.gh-issue-121249.W9Gd09.rst b/Misc/NEWS.d/next/Library/2024-07-10-08-13-34.gh-issue-121249.W9Gd09.rst new file mode 100644 index 00000000000000..2d41fca45bcad9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-07-10-08-13-34.gh-issue-121249.W9Gd09.rst @@ -0,0 +1,3 @@ +Support the :c:expr:`float complex` and :c:expr:`double complex` +C types in the :mod:`struct` module if the compiler has C11 complex +arithmetic. Patch by Sergey B Kirpichev. diff --git a/Misc/NEWS.d/next/Library/2024-08-06-07-24-00.gh-issue-118974.qamsCQ.rst b/Misc/NEWS.d/next/Library/2024-08-06-07-24-00.gh-issue-118974.qamsCQ.rst new file mode 100644 index 00000000000000..79480a69c1a90e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-06-07-24-00.gh-issue-118974.qamsCQ.rst @@ -0,0 +1,2 @@ +Add ``decorator`` parameter to :func:`dataclasses.make_dataclass` +to customize the functional creation of dataclasses. diff --git a/Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst b/Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst new file mode 100644 index 00000000000000..0e5256e7151c5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-23-15-49-10.gh-issue-116810.QLBUU8.rst @@ -0,0 +1,4 @@ +Resolve a memory leak introduced in CPython 3.10's :mod:`ssl` when the +:attr:`ssl.SSLSocket.session` property was accessed. Speeds up read and +write access to said property by no longer unnecessarily cloning session +objects via serialization. diff --git a/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst b/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst deleted file mode 100644 index 89610fa44bf743..00000000000000 --- a/Misc/NEWS.d/next/Library/2024-09-23-18-18-23.gh-issue-124309.iFcarA.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :exc:`AssertionError` when using :func:`!asyncio.staggered.staggered_race` with :attr:`asyncio.eager_task_factory`. diff --git a/Misc/NEWS.d/next/Library/2024-09-25-18-07-51.gh-issue-120378.NlBSz_.rst b/Misc/NEWS.d/next/Library/2024-09-25-18-07-51.gh-issue-120378.NlBSz_.rst new file mode 100644 index 00000000000000..1a8c1427b6b9b9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-25-18-07-51.gh-issue-120378.NlBSz_.rst @@ -0,0 +1,2 @@ +Fix a crash related to an integer overflow in :func:`curses.resizeterm` +and :func:`curses.resize_term`. diff --git a/Misc/NEWS.d/next/Library/2024-09-25-22-06-52.gh-issue-124552.1nQKNM.rst b/Misc/NEWS.d/next/Library/2024-09-25-22-06-52.gh-issue-124552.1nQKNM.rst new file mode 100644 index 00000000000000..39dde4c774ba5d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-25-22-06-52.gh-issue-124552.1nQKNM.rst @@ -0,0 +1 @@ +Improve the accuracy of :mod:`bdb`'s check for the possibility of breakpoint in a frame. This makes it possible to disable unnecessary events in functions. diff --git a/Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst b/Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst new file mode 100644 index 00000000000000..cf9dacf4007c28 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-26-00-35-24.gh-issue-116750.X1aMHI.rst @@ -0,0 +1 @@ +Provide :func:`sys.monitoring.clear_tool_id` to unregister all events and callbacks set by the tool. diff --git a/Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst b/Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst new file mode 100644 index 00000000000000..ac48bd84930745 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-26-13-43-39.gh-issue-124594.peYhsP.rst @@ -0,0 +1 @@ +All :mod:`asyncio` REPL prompts run in the same :class:`context `. Contributed by Bartosz Sławecki. diff --git a/Misc/NEWS.d/next/Library/2024-09-30-19-59-28.gh-issue-66436.4gYN_n.rst b/Misc/NEWS.d/next/Library/2024-09-30-19-59-28.gh-issue-66436.4gYN_n.rst new file mode 100644 index 00000000000000..69a77b01902873 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-30-19-59-28.gh-issue-66436.4gYN_n.rst @@ -0,0 +1,4 @@ +Improved :ref:`prog` default value for :class:`argparse.ArgumentParser`. It +will now include the name of the Python executable along with the module or +package name, or the path to a directory, ZIP file, or directory within a +ZIP file if the code was run that way. diff --git a/Misc/NEWS.d/next/Library/2024-10-01-12-43-42.gh-issue-124835.SVyp3K.rst b/Misc/NEWS.d/next/Library/2024-10-01-12-43-42.gh-issue-124835.SVyp3K.rst new file mode 100644 index 00000000000000..09e5a046f83e49 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-01-12-43-42.gh-issue-124835.SVyp3K.rst @@ -0,0 +1,3 @@ +Make :func:`tomllib.loads` raise :exc:`TypeError` not :exc:`AttributeError` +on bad input types that do not have the ``replace`` attribute. Improve error +message when :class:`bytes` is received. diff --git a/Misc/NEWS.d/next/Library/2024-10-01-17-12-20.gh-issue-124858.Zy0tvT.rst b/Misc/NEWS.d/next/Library/2024-10-01-17-12-20.gh-issue-124858.Zy0tvT.rst new file mode 100644 index 00000000000000..c05d24a7c5aacb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-01-17-12-20.gh-issue-124858.Zy0tvT.rst @@ -0,0 +1 @@ +Fix reference cycles left in tracebacks in :func:`asyncio.open_connection` when used with ``happy_eyeballs_delay`` diff --git a/Misc/NEWS.d/next/Library/2024-10-02-15-05-45.gh-issue-124653.tqsTu9.rst b/Misc/NEWS.d/next/Library/2024-10-02-15-05-45.gh-issue-124653.tqsTu9.rst new file mode 100644 index 00000000000000..6f5ad12d2c2981 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-02-15-05-45.gh-issue-124653.tqsTu9.rst @@ -0,0 +1,2 @@ +Fix detection of the minimal Queue API needed by the :mod:`logging` module. +Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2024-10-02-22-53-48.gh-issue-90102.4qX52R.rst b/Misc/NEWS.d/next/Library/2024-10-02-22-53-48.gh-issue-90102.4qX52R.rst new file mode 100644 index 00000000000000..0e708ed11d21b5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-02-22-53-48.gh-issue-90102.4qX52R.rst @@ -0,0 +1,3 @@ +Skip the ``isatty`` system call during open() when the file is known to not +be a character device. This provides a slight performance improvement when +reading whole files. diff --git a/Misc/NEWS.d/next/Library/2024-10-03-05-00-25.gh-issue-117151.Prdw_W.rst b/Misc/NEWS.d/next/Library/2024-10-03-05-00-25.gh-issue-117151.Prdw_W.rst new file mode 100644 index 00000000000000..a7d6251f1e071f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-03-05-00-25.gh-issue-117151.Prdw_W.rst @@ -0,0 +1,3 @@ +The default buffer size used by :func:`shutil.copyfileobj` has been +increased from 64k to 256k on non-Windows platforms. It was already larger +on Windows. diff --git a/Misc/NEWS.d/next/Library/2024-10-03-19-16-38.gh-issue-123961.ik1Dgs.rst b/Misc/NEWS.d/next/Library/2024-10-03-19-16-38.gh-issue-123961.ik1Dgs.rst new file mode 100644 index 00000000000000..b637b895d0b803 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-03-19-16-38.gh-issue-123961.ik1Dgs.rst @@ -0,0 +1,2 @@ +Convert :mod:`curses` to multi-phase initialization (:pep:`489`), thereby +fixing reference leaks at interpreter shutdown. Patch by Bénédikt Tran. diff --git a/Misc/NEWS.d/next/Library/2024-10-04-12-43-03.gh-issue-69998.DVqOXX.rst b/Misc/NEWS.d/next/Library/2024-10-04-12-43-03.gh-issue-69998.DVqOXX.rst new file mode 100644 index 00000000000000..65388e0b4e7ee4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-04-12-43-03.gh-issue-69998.DVqOXX.rst @@ -0,0 +1,3 @@ +Fix :func:`locale.nl_langinfo` in case when different categories have +different locales. The function now sets temporarily the ``LC_CTYPE`` locale +in some cases. This temporary change affects other threads. diff --git a/Misc/NEWS.d/next/Library/2024-10-08-13-28-22.gh-issue-125096.Vz0W5g.rst b/Misc/NEWS.d/next/Library/2024-10-08-13-28-22.gh-issue-125096.Vz0W5g.rst new file mode 100644 index 00000000000000..c582a2dfe7243c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-10-08-13-28-22.gh-issue-125096.Vz0W5g.rst @@ -0,0 +1,5 @@ +If the :envvar:`PYTHON_BASIC_REPL` environment variable is set, the +:mod:`site` module no longer imports the :mod:`!_pyrepl` module. Moreover, +the :mod:`site` module now respects :option:`-E` and :option:`-I` command +line options: ignore :envvar:`PYTHON_BASIC_REPL` in this case. Patch by +Victor Stinner. diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml index fe0a5e44f8fb15..62978261745d79 100644 --- a/Misc/stable_abi.toml +++ b/Misc/stable_abi.toml @@ -2536,3 +2536,5 @@ added = '3.14' [const.Py_TP_USE_SPEC] added = '3.14' +[function.PyUnicode_Equal] + added = '3.14' diff --git a/Modules/_csv.c b/Modules/_csv.c index a623ea449da779..913560ce4a0ee3 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -367,6 +367,8 @@ static struct PyMemberDef Dialect_memberlist[] = { { NULL } }; +#undef D_OFF + static PyGetSetDef Dialect_getsetlist[] = { { "delimiter", (getter)Dialect_get_delimiter}, { "escapechar", (getter)Dialect_get_escapechar}, @@ -502,6 +504,7 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) DIALECT_GETATTR(skipinitialspace, "skipinitialspace"); DIALECT_GETATTR(strict, "strict"); } +#undef DIALECT_GETATTR /* check types and convert to C values */ #define DIASET(meth, name, target, src, dflt) \ @@ -515,6 +518,7 @@ dialect_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) DIASET(_set_int, "quoting", &self->quoting, quoting, QUOTE_MINIMAL); DIASET(_set_bool, "skipinitialspace", &self->skipinitialspace, skipinitialspace, false); DIASET(_set_bool, "strict", &self->strict, strict, false); +#undef DIASET /* validate options */ if (dialect_check_quoting(self->quoting)) @@ -1026,6 +1030,8 @@ static struct PyMemberDef Reader_memberlist[] = { { NULL } }; +#undef R_OFF + static PyType_Slot Reader_Type_slots[] = { {Py_tp_doc, (char*)Reader_Type_doc}, @@ -1441,6 +1447,8 @@ static struct PyMemberDef Writer_memberlist[] = { { NULL } }; +#undef W_OFF + static int Writer_traverse(WriterObj *self, visitproc visit, void *arg) { diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index ece6b13c78851f..27d5df08de933e 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -105,8 +105,9 @@ static const char PyCursesVersion[] = "2.2"; #endif #include "Python.h" -#include "pycore_long.h" // _PyLong_GetZero() -#include "pycore_structseq.h" // _PyStructSequence_NewType() +#include "pycore_capsule.h" // _PyCapsule_SetTraverse() +#include "pycore_long.h" // _PyLong_GetZero() +#include "pycore_structseq.h" // _PyStructSequence_NewType() #ifdef __hpux #define STRICT_SYSV_CURSES @@ -159,31 +160,41 @@ typedef chtype attr_t; /* No attr_t type is available */ #define _CURSES_PAIR_CONTENT_FUNC pair_content #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ -typedef struct _cursesmodule_state { - PyObject *error; // PyCursesError - PyTypeObject *window_type; // PyCursesWindow_Type -} _cursesmodule_state; +typedef struct { + PyObject *error; // curses exception type + PyTypeObject *window_type; // exposed by PyCursesWindow_Type +} cursesmodule_state; -// For now, we keep a global state variable to prepare for PEP 489. -static _cursesmodule_state curses_global_state; +static inline cursesmodule_state * +get_cursesmodule_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (cursesmodule_state *)state; +} -static inline _cursesmodule_state * -get_cursesmodule_state(PyObject *Py_UNUSED(module)) +static inline cursesmodule_state * +get_cursesmodule_state_by_cls(PyTypeObject *cls) { - return &curses_global_state; + void *state = PyType_GetModuleState(cls); + assert(state != NULL); + return (cursesmodule_state *)state; } -static inline _cursesmodule_state * -get_cursesmodule_state_by_win(PyCursesWindowObject *Py_UNUSED(win)) +static inline cursesmodule_state * +get_cursesmodule_state_by_win(PyCursesWindowObject *win) { - return &curses_global_state; + return get_cursesmodule_state_by_cls(Py_TYPE(win)); } /*[clinic input] module _curses -class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" +class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ae6cb623018f2cbc]*/ + +/* Indicate whether the module has already been loaded or not. */ +static int curses_module_loaded = 0; /* Tells whether setupterm() has been called to initialise terminfo. */ static int curses_setupterm_called = FALSE; @@ -204,8 +215,8 @@ static const char *curses_screen_encoding = NULL; * set and this returns 0. Otherwise, this returns 1. * * Since this function can be called in functions that do not - * have a direct access to the module's state, the exception - * type is directly taken from the global state for now. + * have a direct access to the module's state, '_curses.error' + * is imported on demand. */ static inline int _PyCursesCheckFunction(int called, const char *funcname) @@ -213,7 +224,12 @@ _PyCursesCheckFunction(int called, const char *funcname) if (called == TRUE) { return 1; } - PyErr_Format(curses_global_state.error, "must call %s() first", funcname); + PyObject *exc = _PyImport_GetModuleAttrString("_curses", "error"); + if (exc != NULL) { + PyErr_Format(exc, "must call %s() first", funcname); + Py_DECREF(exc); + } + assert(PyErr_Occurred()); return 0; } @@ -230,7 +246,7 @@ _PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcnam if (called == TRUE) { return 1; } - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_Format(state->error, "must call %s() first", funcname); return 0; } @@ -268,7 +284,7 @@ _PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcnam /* Utility Functions */ static inline void -_PyCursesSetError(_cursesmodule_state *state, const char *funcname) +_PyCursesSetError(cursesmodule_state *state, const char *funcname) { if (funcname == NULL) { PyErr_SetString(state->error, catchall_ERR); @@ -289,7 +305,7 @@ PyCursesCheckERR(PyObject *module, int code, const char *fname) if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); _PyCursesSetError(state, fname); return NULL; } @@ -301,7 +317,7 @@ PyCursesCheckERR_ForWin(PyCursesWindowObject *win, int code, const char *fname) if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *state = get_cursesmodule_state_by_win(win); + cursesmodule_state *state = get_cursesmodule_state_by_win(win); _PyCursesSetError(state, fname); return NULL; } @@ -626,32 +642,10 @@ class component_converter(CConverter): [python start generated code]*/ /*[python end generated code: output=da39a3ee5e6b4b0d input=38e9be01d33927fb]*/ -/* Function versions of the 3 functions for testing whether curses has been - initialised or not. */ - -static int func_PyCursesSetupTermCalled(void) -{ - return _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); -} - -static int func_PyCursesInitialised(void) -{ - return _PyCursesCheckFunction(curses_initscr_called, "initscr"); -} - -static int func_PyCursesInitialisedColor(void) -{ - return _PyCursesCheckFunction(curses_start_color_called, "start_color"); -} - /***************************************************************************** The Window Object ******************************************************************************/ -/* Definition of the window type */ - -PyTypeObject PyCursesWindow_Type; - /* Function prototype macros for Window object X - function name @@ -761,10 +755,9 @@ Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") /* Allocation and deallocation of Window Objects */ static PyObject * -PyCursesWindow_New(WINDOW *win, const char *encoding) +PyCursesWindow_New(cursesmodule_state *state, + WINDOW *win, const char *encoding) { - PyCursesWindowObject *wo; - if (encoding == NULL) { #if defined(MS_WINDOWS) char *buffer[100]; @@ -776,15 +769,20 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) } #elif defined(CODESET) const char *codeset = nl_langinfo(CODESET); - if (codeset != NULL && codeset[0] != 0) + if (codeset != NULL && codeset[0] != 0) { encoding = codeset; + } #endif - if (encoding == NULL) + if (encoding == NULL) { encoding = "utf-8"; + } } - wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type); - if (wo == NULL) return NULL; + PyCursesWindowObject *wo = PyObject_GC_New(PyCursesWindowObject, + state->window_type); + if (wo == NULL) { + return NULL; + } wo->win = win; wo->encoding = _PyMem_Strdup(encoding); if (wo->encoding == NULL) { @@ -792,12 +790,16 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) PyErr_NoMemory(); return NULL; } + PyObject_GC_Track((PyObject *)wo); return (PyObject *)wo; } static void -PyCursesWindow_Dealloc(PyCursesWindowObject *wo) +PyCursesWindow_dealloc(PyObject *self) { + PyTypeObject *window_type = Py_TYPE(self); + PyObject_GC_UnTrack(self); + PyCursesWindowObject *wo = (PyCursesWindowObject *)self; if (wo->win != stdscr && wo->win != NULL) { // silently ignore errors in delwin(3) (void)delwin(wo->win); @@ -805,7 +807,15 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) if (wo->encoding != NULL) { PyMem_Free(wo->encoding); } - PyObject_Free(wo); + window_type->tp_free(self); + Py_DECREF(window_type); +} + +static int +PyCursesWindow_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; } /* Addch, Addstr, Addnstr */ @@ -1404,12 +1414,13 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_SetString(state->error, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + return PyCursesWindow_New(state, win, NULL); } /*[clinic input] @@ -1557,7 +1568,7 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); if (!PyErr_Occurred()) { - _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_SetString(state->error, "no input"); } return NULL; @@ -1617,7 +1628,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_SetString(state->error, "no input"); return NULL; } @@ -2131,7 +2142,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_SetString(state->error, "noutrefresh() called for a pad " "requires 6 arguments"); @@ -2158,7 +2169,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) /*[clinic input] _curses.window.overlay - destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->window_type") [ sminrow: int @@ -2187,7 +2198,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, PyCursesWindowObject *destwin, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=82bb2c4cb443ca58 input=7edd23ad22cc1984]*/ +/*[clinic end generated code: output=82bb2c4cb443ca58 input=6e4b32a7c627a356]*/ { int rtn; @@ -2205,7 +2216,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, /*[clinic input] _curses.window.overwrite - destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *", subclass_of="clinic_state()->window_type") [ sminrow: int @@ -2235,7 +2246,7 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0]*/ +/*[clinic end generated code: output=12ae007d1681be28 input=d83dd8b24ff2bcc9]*/ { int rtn; @@ -2356,7 +2367,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_SetString(state->error, "refresh() for a pad requires 6 arguments"); return NULL; @@ -2439,12 +2450,13 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_SetString(state->error, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, self->encoding); + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + return PyCursesWindow_New(state, win, self->encoding); } /*[clinic input] @@ -2582,9 +2594,11 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *P return 0; } +#define clinic_state() (get_cursesmodule_state_by_cls(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" +#undef clinic_state -static PyMethodDef PyCursesWindow_Methods[] = { +static PyMethodDef PyCursesWindow_methods[] = { _CURSES_WINDOW_ADDCH_METHODDEF _CURSES_WINDOW_ADDNSTR_METHODDEF _CURSES_WINDOW_ADDSTR_METHODDEF @@ -2678,42 +2692,27 @@ static PyGetSetDef PyCursesWindow_getsets[] = { {NULL, NULL, NULL, NULL } /* sentinel */ }; -/* -------------------------------------------------------*/ +static PyType_Slot PyCursesWindow_Type_slots[] = { + {Py_tp_methods, PyCursesWindow_methods}, + {Py_tp_getset, PyCursesWindow_getsets}, + {Py_tp_dealloc, PyCursesWindow_dealloc}, + {Py_tp_traverse, PyCursesWindow_traverse}, + {0, NULL} +}; -PyTypeObject PyCursesWindow_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_curses.window", /*tp_name*/ - sizeof(PyCursesWindowObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PyCursesWindow_Methods, /*tp_methods*/ - 0, /* tp_members */ - PyCursesWindow_getsets, /* tp_getset */ +static PyType_Spec PyCursesWindow_Type_spec = { + .name = "_curses.window", + .basicsize = sizeof(PyCursesWindowObject), + .flags = Py_TPFLAGS_DEFAULT + | Py_TPFLAGS_DISALLOW_INSTANTIATION + | Py_TPFLAGS_IMMUTABLETYPE + | Py_TPFLAGS_HEAPTYPE + | Py_TPFLAGS_HAVE_GC, + .slots = PyCursesWindow_Type_slots }; +/* -------------------------------------------------------*/ + /* Function Body Macros - They are ugly but very, very useful. ;-) X - function name @@ -2856,7 +2855,7 @@ _curses_color_content_impl(PyObject *module, int color_number) PyCursesStatefulInitialisedColor(module); if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_Format(state->error, "%s() returned ERR", Py_STRINGIFY(_COLOR_CONTENT_FUNC)); return NULL; @@ -3096,7 +3095,7 @@ _curses_getmouse_impl(PyObject *module) rtn = getmouse( &event ); if (rtn == ERR) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, "getmouse() returned ERR"); return NULL; } @@ -3191,11 +3190,12 @@ _curses_getwin(PyObject *module, PyObject *file) fseek(fp, 0, 0); win = getwin(fp); if (win == NULL) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, catchall_NULL); goto error; } - res = PyCursesWindow_New(win, NULL); + cursesmodule_state *state = get_cursesmodule_state(module); + res = PyCursesWindow_New(state, win, NULL); error: fclose(fp); @@ -3341,7 +3341,7 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) COLOR_PAIRS - 1); } else { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_Format(state->error, "%s() returned ERR", Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC)); } @@ -3367,13 +3367,14 @@ _curses_initscr_impl(PyObject *module) if (curses_initscr_called) { wrefresh(stdscr); - return (PyObject *)PyCursesWindow_New(stdscr, NULL); + cursesmodule_state *state = get_cursesmodule_state(module); + return PyCursesWindow_New(state, stdscr, NULL); } win = initscr(); if (win == NULL) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, catchall_NULL); return NULL; } @@ -3470,12 +3471,13 @@ _curses_initscr_impl(PyObject *module) SetDictInt("COLS", COLS); #undef SetDictInt - PyCursesWindowObject *winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); + cursesmodule_state *state = get_cursesmodule_state(module); + PyObject *winobj = PyCursesWindow_New(state, win, NULL); if (winobj == NULL) { return NULL; } - curses_screen_encoding = winobj->encoding; - return (PyObject *)winobj; + curses_screen_encoding = ((PyCursesWindowObject *)winobj)->encoding; + return winobj; } /*[clinic input] @@ -3503,7 +3505,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) sys_stdout = PySys_GetObject("stdout"); if (sys_stdout == NULL || sys_stdout == Py_None) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, "lost sys.stdout"); return NULL; } @@ -3524,7 +3526,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) s = "setupterm: could not find terminfo database"; } - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, s); return NULL; } @@ -3842,12 +3844,13 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) win = newpad(nlines, ncols); if (win == NULL) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + cursesmodule_state *state = get_cursesmodule_state(module); + return PyCursesWindow_New(state, win, NULL); } /*[clinic input] @@ -3882,12 +3885,13 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, catchall_NULL); return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + cursesmodule_state *state = get_cursesmodule_state(module); + return PyCursesWindow_New(state, win, NULL); } /*[clinic input] @@ -4001,7 +4005,7 @@ _curses_pair_content_impl(PyObject *module, int pair_number) COLOR_PAIRS - 1); } else { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_Format(state->error, "%s() returned ERR", Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC)); } @@ -4204,9 +4208,9 @@ NoArgNoReturnFunctionBody(resetty) /*[clinic input] _curses.resizeterm - nlines: int + nlines: short Height. - ncols: int + ncols: short Width. / @@ -4217,8 +4221,8 @@ window dimensions (in particular the SIGWINCH handler). [clinic start generated code]*/ static PyObject * -_curses_resizeterm_impl(PyObject *module, int nlines, int ncols) -/*[clinic end generated code: output=56d6bcc5194ad055 input=0fca02ebad5ffa82]*/ +_curses_resizeterm_impl(PyObject *module, short nlines, short ncols) +/*[clinic end generated code: output=4de3abab50c67f02 input=414e92a63e3e9899]*/ { PyObject *result; @@ -4240,9 +4244,9 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) /*[clinic input] _curses.resize_term - nlines: int + nlines: short Height. - ncols: int + ncols: short Width. / @@ -4256,8 +4260,8 @@ without additional interaction with the application. [clinic start generated code]*/ static PyObject * -_curses_resize_term_impl(PyObject *module, int nlines, int ncols) -/*[clinic end generated code: output=9e26d8b9ea311ed2 input=2197edd05b049ed4]*/ +_curses_resize_term_impl(PyObject *module, short nlines, short ncols) +/*[clinic end generated code: output=46c6d749fa291dbd input=276afa43d8ea7091]*/ { PyObject *result; @@ -4332,7 +4336,7 @@ _curses_start_color_impl(PyObject *module) PyCursesStatefulInitialised(module); if (start_color() == ERR) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, "start_color() returned ERR"); return NULL; } @@ -4485,7 +4489,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, "tparm() returned NULL"); return NULL; } @@ -4687,7 +4691,7 @@ _curses_use_default_colors_impl(PyObject *module) if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *state = get_cursesmodule_state(module); + cursesmodule_state *state = get_cursesmodule_state(module); PyErr_SetString(state->error, "use_default_colors() returned ERR"); return NULL; } @@ -4768,7 +4772,7 @@ _curses_has_extended_color_support_impl(PyObject *module) /* List of functions defined in the module */ -static PyMethodDef PyCurses_methods[] = { +static PyMethodDef cursesmodule_methods[] = { _CURSES_BAUDRATE_METHODDEF _CURSES_BEEP_METHODDEF _CURSES_CAN_CHANGE_COLOR_METHODDEF @@ -4853,41 +4857,148 @@ static PyMethodDef PyCurses_methods[] = { {NULL, NULL} /* sentinel */ }; -/* Initialization function for the module */ +/* Module C API */ +/* Function versions of the 3 functions for testing whether curses has been + initialised or not. */ -static struct PyModuleDef _cursesmodule = { - PyModuleDef_HEAD_INIT, - "_curses", - NULL, - -1, - PyCurses_methods, - NULL, - NULL, - NULL, - NULL -}; +static inline int +curses_capi_setupterm_called(void) +{ + return _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); +} + +static inline int +curses_capi_initscr_called(void) +{ + return _PyCursesCheckFunction(curses_initscr_called, "initscr"); +} + +static inline int +curses_capi_start_color_called(void) +{ + return _PyCursesCheckFunction(curses_start_color_called, "start_color"); +} + +static void * +curses_capi_new(cursesmodule_state *state) +{ + assert(state->window_type != NULL); + void **capi = (void **)PyMem_Calloc(PyCurses_API_pointers, sizeof(void *)); + if (capi == NULL) { + PyErr_NoMemory(); + return NULL; + } + capi[0] = (void *)Py_NewRef(state->window_type); + capi[1] = curses_capi_setupterm_called; + capi[2] = curses_capi_initscr_called; + capi[3] = curses_capi_start_color_called; + return (void *)capi; +} + +static void +curses_capi_free(void *capi) +{ + assert(capi != NULL); + void **capi_ptr = (void **)capi; + // In free-threaded builds, capi_ptr[0] may have been already cleared + // by curses_capi_capsule_destructor(), hence the use of Py_XDECREF(). + Py_XDECREF(capi_ptr[0]); // decref curses window type + PyMem_Free(capi_ptr); +} + +/* Module C API Capsule */ + +static void +curses_capi_capsule_destructor(PyObject *op) +{ + void *capi = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); + curses_capi_free(capi); +} + +static int +curses_capi_capsule_traverse(PyObject *op, visitproc visit, void *arg) +{ + void **capi_ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); + assert(capi_ptr != NULL); + Py_VISIT(capi_ptr[0]); // visit curses window type + return 0; +} + +static int +curses_capi_capsule_clear(PyObject *op) +{ + void **capi_ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); + assert(capi_ptr != NULL); + Py_CLEAR(capi_ptr[0]); // clear curses window type + return 0; +} + +static PyObject * +curses_capi_capsule_new(void *capi) +{ + PyObject *capsule = PyCapsule_New(capi, PyCurses_CAPSULE_NAME, + curses_capi_capsule_destructor); + if (capsule == NULL) { + return NULL; + } + if (_PyCapsule_SetTraverse(capsule, + curses_capi_capsule_traverse, + curses_capi_capsule_clear) < 0) + { + Py_DECREF(capsule); + return NULL; + } + return capsule; +} + +/* Module initialization and cleanup functions */ + +static int +cursesmodule_traverse(PyObject *mod, visitproc visit, void *arg) +{ + cursesmodule_state *state = get_cursesmodule_state(mod); + Py_VISIT(state->error); + Py_VISIT(state->window_type); + return 0; +} + +static int +cursesmodule_clear(PyObject *mod) +{ + cursesmodule_state *state = get_cursesmodule_state(mod); + Py_CLEAR(state->error); + Py_CLEAR(state->window_type); + return 0; +} static void -curses_destructor(PyObject *op) +cursesmodule_free(void *mod) { - void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); - Py_DECREF(*(void **)ptr); - PyMem_Free(ptr); + (void)cursesmodule_clear((PyObject *)mod); + curses_module_loaded = 0; // allow reloading once garbage-collected } static int cursesmodule_exec(PyObject *module) { - _cursesmodule_state *state = get_cursesmodule_state(module); + if (curses_module_loaded) { + PyErr_SetString(PyExc_ImportError, + "module 'curses' can only be loaded once per process"); + return -1; + } + curses_module_loaded = 1; + + cursesmodule_state *state = get_cursesmodule_state(module); /* Initialize object type */ - if (PyType_Ready(&PyCursesWindow_Type) < 0) { + state->window_type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PyCursesWindow_Type_spec, NULL); + if (state->window_type == NULL) { return -1; } - if (PyModule_AddType(module, &PyCursesWindow_Type) < 0) { + if (PyModule_AddType(module, state->window_type) < 0) { return -1; } - state->window_type = &PyCursesWindow_Type; /* Add some symbolic constants to the module */ PyObject *module_dict = PyModule_GetDict(module); @@ -4895,27 +5006,19 @@ cursesmodule_exec(PyObject *module) return -1; } - void **PyCurses_API = PyMem_Calloc(PyCurses_API_pointers, sizeof(void *)); - if (PyCurses_API == NULL) { - PyErr_NoMemory(); + /* Create the C API object */ + void *capi = curses_capi_new(state); + if (capi == NULL) { return -1; } - /* Initialize the C API pointer array */ - PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type); - PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled; - PyCurses_API[2] = (void *)func_PyCursesInitialised; - PyCurses_API[3] = (void *)func_PyCursesInitialisedColor; - /* Add a capsule for the C API */ - PyObject *c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, - curses_destructor); - if (c_api_object == NULL) { - Py_DECREF(PyCurses_API[0]); - PyMem_Free(PyCurses_API); + PyObject *capi_capsule = curses_capi_capsule_new(capi); + if (capi_capsule == NULL) { + curses_capi_free(capi); return -1; } - int rc = PyDict_SetItemString(module_dict, "_C_API", c_api_object); - Py_DECREF(c_api_object); + int rc = PyDict_SetItemString(module_dict, "_C_API", capi_capsule); + Py_DECREF(capi_capsule); if (rc < 0) { return -1; } @@ -4926,7 +5029,6 @@ cursesmodule_exec(PyObject *module) return -1; } rc = PyDict_SetItemString(module_dict, "error", state->error); - Py_DECREF(state->error); if (rc < 0) { return -1; } @@ -5118,26 +5220,28 @@ cursesmodule_exec(PyObject *module) return 0; } +/* Initialization function for the module */ + +static PyModuleDef_Slot cursesmodule_slots[] = { + {Py_mod_exec, cursesmodule_exec}, + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0, NULL} +}; + +static struct PyModuleDef cursesmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_curses", + .m_size = sizeof(cursesmodule_state), + .m_methods = cursesmodule_methods, + .m_slots = cursesmodule_slots, + .m_traverse = cursesmodule_traverse, + .m_clear = cursesmodule_clear, + .m_free = cursesmodule_free +}; + PyMODINIT_FUNC PyInit__curses(void) { - // create the module - PyObject *mod = PyModule_Create(&_cursesmodule); - if (mod == NULL) { - goto error; - } -#ifdef Py_GIL_DISABLED - if (PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED) < 0) { - goto error; - } -#endif - // populate the module - if (cursesmodule_exec(mod) < 0) { - goto error; - } - return mod; - -error: - Py_XDECREF(mod); - return NULL; + return PyModuleDef_Init(&cursesmodule); } diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 1238e6074246d0..6622f2cabb908b 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -346,7 +346,7 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, /* buffering */ if (buffering < 0) { - PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(isatty)); + PyObject *res = PyObject_CallMethodNoArgs(raw, &_Py_ID(_isatty_open_only)); if (res == NULL) goto error; isatty = PyObject_IsTrue(res); diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 8dae465fd20f8b..f374592eb95967 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -12,9 +12,6 @@ #ifdef HAVE_SYS_TYPES_H # include #endif -#ifdef HAVE_SYS_STAT_H -# include -#endif #ifdef HAVE_IO_H # include #endif @@ -86,6 +83,7 @@ typedef struct { } fileio; #define PyFileIO_Check(state, op) (PyObject_TypeCheck((op), state->PyFileIO_Type)) +#define _PyFileIO_CAST(op) _Py_CAST(fileio*, (op)) /* Forward declarations */ static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool suppress_pipe_error); @@ -93,15 +91,16 @@ static PyObject* portable_lseek(fileio *self, PyObject *posobj, int whence, bool int _PyFileIO_closed(PyObject *self) { - return ((fileio *)self)->fd < 0; + return (_PyFileIO_CAST(self)->fd < 0); } /* Because this can call arbitrary code, it shouldn't be called when the refcount is 0 (that is, not directly from tp_dealloc unless the refcount has been temporarily re-incremented). */ static PyObject * -fileio_dealloc_warn(fileio *self, PyObject *source) +fileio_dealloc_warn(PyObject *op, PyObject *source) { + fileio *self = _PyFileIO_CAST(op); if (self->fd >= 0 && self->closefd) { PyObject *exc = PyErr_GetRaisedException(); if (PyErr_ResourceWarning(source, 1, "unclosed file %R", source)) { @@ -171,7 +170,7 @@ _io_FileIO_close_impl(fileio *self, PyTypeObject *cls) exc = PyErr_GetRaisedException(); } if (self->finalizing) { - PyObject *r = fileio_dealloc_warn(self, (PyObject *) self); + PyObject *r = fileio_dealloc_warn((PyObject*)self, (PyObject *) self); if (r) { Py_DECREF(r); } @@ -192,23 +191,22 @@ _io_FileIO_close_impl(fileio *self, PyTypeObject *cls) static PyObject * fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - fileio *self; - assert(type != NULL && type->tp_alloc != NULL); - self = (fileio *) type->tp_alloc(type, 0); - if (self != NULL) { - self->fd = -1; - self->created = 0; - self->readable = 0; - self->writable = 0; - self->appending = 0; - self->seekable = -1; - self->stat_atopen = NULL; - self->closefd = 1; - self->weakreflist = NULL; + fileio *self = (fileio *) type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; } + self->fd = -1; + self->created = 0; + self->readable = 0; + self->writable = 0; + self->appending = 0; + self->seekable = -1; + self->stat_atopen = NULL; + self->closefd = 1; + self->weakreflist = NULL; return (PyObject *) self; } @@ -539,36 +537,43 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, } static int -fileio_traverse(fileio *self, visitproc visit, void *arg) +fileio_traverse(PyObject *op, visitproc visit, void *arg) { + fileio *self = _PyFileIO_CAST(op); Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; } static int -fileio_clear(fileio *self) +fileio_clear(PyObject *op) { + fileio *self = _PyFileIO_CAST(op); Py_CLEAR(self->dict); return 0; } static void -fileio_dealloc(fileio *self) +fileio_dealloc(PyObject *op) { - PyTypeObject *tp = Py_TYPE(self); + fileio *self = _PyFileIO_CAST(op); self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) + if (_PyIOBase_finalize(op) < 0) { return; + } + _PyObject_GC_UNTRACK(self); if (self->stat_atopen != NULL) { PyMem_Free(self->stat_atopen); self->stat_atopen = NULL; } - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - (void)fileio_clear(self); - tp->tp_free((PyObject *)self); + if (self->weakreflist != NULL) { + PyObject_ClearWeakRefs(op); + } + (void)fileio_clear(op); + + PyTypeObject *tp = Py_TYPE(op); + tp->tp_free(op); Py_DECREF(tp); } @@ -1151,18 +1156,20 @@ mode_string(fileio *self) } static PyObject * -fileio_repr(fileio *self) +fileio_repr(PyObject *op) { - PyObject *nameobj, *res; - const char *type_name = Py_TYPE((PyObject *) self)->tp_name; + fileio *self = _PyFileIO_CAST(op); + const char *type_name = Py_TYPE(self)->tp_name; if (self->fd < 0) { return PyUnicode_FromFormat("<%.100s [closed]>", type_name); } + PyObject *nameobj; if (PyObject_GetOptionalAttr((PyObject *) self, &_Py_ID(name), &nameobj) < 0) { return NULL; } + PyObject *res; if (nameobj == NULL) { res = PyUnicode_FromFormat( "<%.100s fd=%d mode='%s' closefd=%s>", @@ -1208,6 +1215,24 @@ _io_FileIO_isatty_impl(fileio *self) return PyBool_FromLong(res); } +/* Checks whether the file is a TTY using an open-only optimization. + + TTYs are always character devices. If the interpreter knows a file is + not a character device when it would call ``isatty``, can skip that + call. Inside ``open()`` there is a fresh stat result that contains that + information. Use the stat result to skip a system call. Outside of that + context TOCTOU issues (the fd could be arbitrarily modified by + surrounding code). */ +static PyObject * +_io_FileIO_isatty_open_only(PyObject *op, PyObject *Py_UNUSED(ignored)) +{ + fileio *self = _PyFileIO_CAST(op); + if (self->stat_atopen != NULL && !S_ISCHR(self->stat_atopen->st_mode)) { + Py_RETURN_FALSE; + } + return _io_FileIO_isatty_impl(self); +} + #include "clinic/fileio.c.h" static PyMethodDef fileio_methods[] = { @@ -1224,7 +1249,8 @@ static PyMethodDef fileio_methods[] = { _IO_FILEIO_WRITABLE_METHODDEF _IO_FILEIO_FILENO_METHODDEF _IO_FILEIO_ISATTY_METHODDEF - {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, + {"_isatty_open_only", _io_FileIO_isatty_open_only, METH_NOARGS}, + {"_dealloc_warn", fileio_dealloc_warn, METH_O, NULL}, {"__reduce__", _PyIOBase_cannot_pickle, METH_NOARGS}, {"__reduce_ex__", _PyIOBase_cannot_pickle, METH_O}, {NULL, NULL} /* sentinel */ @@ -1233,26 +1259,30 @@ static PyMethodDef fileio_methods[] = { /* 'closed' and 'mode' are attributes for backwards compatibility reasons. */ static PyObject * -get_closed(fileio *self, void *closure) +fileio_get_closed(PyObject *op, void *closure) { + fileio *self = _PyFileIO_CAST(op); return PyBool_FromLong((long)(self->fd < 0)); } static PyObject * -get_closefd(fileio *self, void *closure) +fileio_get_closefd(PyObject *op, void *closure) { + fileio *self = _PyFileIO_CAST(op); return PyBool_FromLong((long)(self->closefd)); } static PyObject * -get_mode(fileio *self, void *closure) +fileio_get_mode(PyObject *op, void *closure) { + fileio *self = _PyFileIO_CAST(op); return PyUnicode_FromString(mode_string(self)); } static PyObject * -get_blksize(fileio *self, void *closure) +fileio_get_blksize(PyObject *op, void *closure) { + fileio *self = _PyFileIO_CAST(op); #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE if (self->stat_atopen != NULL && self->stat_atopen->st_blksize > 1) { return PyLong_FromLong(self->stat_atopen->st_blksize); @@ -1262,11 +1292,11 @@ get_blksize(fileio *self, void *closure) } static PyGetSetDef fileio_getsetlist[] = { - {"closed", (getter)get_closed, NULL, "True if the file is closed"}, - {"closefd", (getter)get_closefd, NULL, + {"closed", fileio_get_closed, NULL, "True if the file is closed"}, + {"closefd", fileio_get_closefd, NULL, "True if the file descriptor will be closed by close()."}, - {"mode", (getter)get_mode, NULL, "String giving the file mode"}, - {"_blksize", (getter)get_blksize, NULL, "Stat st_blksize if available"}, + {"mode", fileio_get_mode, NULL, "String giving the file mode"}, + {"_blksize", fileio_get_blksize, NULL, "Stat st_blksize if available"}, {NULL}, }; diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index ec5c298066a587..d7cb5abfdc0abd 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -1128,6 +1128,7 @@ static PyMethodDef winconsoleio_methods[] = { _IO__WINDOWSCONSOLEIO_WRITABLE_METHODDEF _IO__WINDOWSCONSOLEIO_FILENO_METHODDEF _IO__WINDOWSCONSOLEIO_ISATTY_METHODDEF + {"_isatty_open_only", (PyCFunction)_io__WindowsConsoleIO_isatty, METH_NOARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_localemodule.c b/Modules/_localemodule.c index de7395b610e133..ce77c4072a6aea 100644 --- a/Modules/_localemodule.c +++ b/Modules/_localemodule.c @@ -144,6 +144,17 @@ locale_is_ascii(const char *str) return (strlen(str) == 1 && ((unsigned char)str[0]) <= 127); } +static int +is_all_ascii(const char *str) +{ + for (; *str; str++) { + if ((unsigned char)*str > 127) { + return 0; + } + } + return 1; +} + static int locale_decode_monetary(PyObject *dict, struct lconv *lc) { @@ -478,113 +489,153 @@ _locale__getdefaultlocale_impl(PyObject *module) #endif #ifdef HAVE_LANGINFO_H -#define LANGINFO(X) {#X, X} +#define LANGINFO(X, Y) {#X, X, Y} static struct langinfo_constant{ - char* name; + const char *name; int value; + int category; } langinfo_constants[] = { /* These constants should exist on any langinfo implementation */ - LANGINFO(DAY_1), - LANGINFO(DAY_2), - LANGINFO(DAY_3), - LANGINFO(DAY_4), - LANGINFO(DAY_5), - LANGINFO(DAY_6), - LANGINFO(DAY_7), - - LANGINFO(ABDAY_1), - LANGINFO(ABDAY_2), - LANGINFO(ABDAY_3), - LANGINFO(ABDAY_4), - LANGINFO(ABDAY_5), - LANGINFO(ABDAY_6), - LANGINFO(ABDAY_7), - - LANGINFO(MON_1), - LANGINFO(MON_2), - LANGINFO(MON_3), - LANGINFO(MON_4), - LANGINFO(MON_5), - LANGINFO(MON_6), - LANGINFO(MON_7), - LANGINFO(MON_8), - LANGINFO(MON_9), - LANGINFO(MON_10), - LANGINFO(MON_11), - LANGINFO(MON_12), - - LANGINFO(ABMON_1), - LANGINFO(ABMON_2), - LANGINFO(ABMON_3), - LANGINFO(ABMON_4), - LANGINFO(ABMON_5), - LANGINFO(ABMON_6), - LANGINFO(ABMON_7), - LANGINFO(ABMON_8), - LANGINFO(ABMON_9), - LANGINFO(ABMON_10), - LANGINFO(ABMON_11), - LANGINFO(ABMON_12), + LANGINFO(DAY_1, LC_TIME), + LANGINFO(DAY_2, LC_TIME), + LANGINFO(DAY_3, LC_TIME), + LANGINFO(DAY_4, LC_TIME), + LANGINFO(DAY_5, LC_TIME), + LANGINFO(DAY_6, LC_TIME), + LANGINFO(DAY_7, LC_TIME), + + LANGINFO(ABDAY_1, LC_TIME), + LANGINFO(ABDAY_2, LC_TIME), + LANGINFO(ABDAY_3, LC_TIME), + LANGINFO(ABDAY_4, LC_TIME), + LANGINFO(ABDAY_5, LC_TIME), + LANGINFO(ABDAY_6, LC_TIME), + LANGINFO(ABDAY_7, LC_TIME), + + LANGINFO(MON_1, LC_TIME), + LANGINFO(MON_2, LC_TIME), + LANGINFO(MON_3, LC_TIME), + LANGINFO(MON_4, LC_TIME), + LANGINFO(MON_5, LC_TIME), + LANGINFO(MON_6, LC_TIME), + LANGINFO(MON_7, LC_TIME), + LANGINFO(MON_8, LC_TIME), + LANGINFO(MON_9, LC_TIME), + LANGINFO(MON_10, LC_TIME), + LANGINFO(MON_11, LC_TIME), + LANGINFO(MON_12, LC_TIME), + + LANGINFO(ABMON_1, LC_TIME), + LANGINFO(ABMON_2, LC_TIME), + LANGINFO(ABMON_3, LC_TIME), + LANGINFO(ABMON_4, LC_TIME), + LANGINFO(ABMON_5, LC_TIME), + LANGINFO(ABMON_6, LC_TIME), + LANGINFO(ABMON_7, LC_TIME), + LANGINFO(ABMON_8, LC_TIME), + LANGINFO(ABMON_9, LC_TIME), + LANGINFO(ABMON_10, LC_TIME), + LANGINFO(ABMON_11, LC_TIME), + LANGINFO(ABMON_12, LC_TIME), #ifdef RADIXCHAR /* The following are not available with glibc 2.0 */ - LANGINFO(RADIXCHAR), - LANGINFO(THOUSEP), + LANGINFO(RADIXCHAR, LC_NUMERIC), + LANGINFO(THOUSEP, LC_NUMERIC), /* YESSTR and NOSTR are deprecated in glibc, since they are a special case of message translation, which should be rather done using gettext. So we don't expose it to Python in the first place. - LANGINFO(YESSTR), - LANGINFO(NOSTR), + LANGINFO(YESSTR, LC_MESSAGES), + LANGINFO(NOSTR, LC_MESSAGES), */ - LANGINFO(CRNCYSTR), + LANGINFO(CRNCYSTR, LC_MONETARY), #endif - LANGINFO(D_T_FMT), - LANGINFO(D_FMT), - LANGINFO(T_FMT), - LANGINFO(AM_STR), - LANGINFO(PM_STR), + LANGINFO(D_T_FMT, LC_TIME), + LANGINFO(D_FMT, LC_TIME), + LANGINFO(T_FMT, LC_TIME), + LANGINFO(AM_STR, LC_TIME), + LANGINFO(PM_STR, LC_TIME), /* The following constants are available only with XPG4, but... OpenBSD doesn't have CODESET but has T_FMT_AMPM, and doesn't have a few of the others. Solution: ifdef-test them all. */ #ifdef CODESET - LANGINFO(CODESET), + LANGINFO(CODESET, LC_CTYPE), #endif #ifdef T_FMT_AMPM - LANGINFO(T_FMT_AMPM), + LANGINFO(T_FMT_AMPM, LC_TIME), #endif #ifdef ERA - LANGINFO(ERA), + LANGINFO(ERA, LC_TIME), #endif #ifdef ERA_D_FMT - LANGINFO(ERA_D_FMT), + LANGINFO(ERA_D_FMT, LC_TIME), #endif #ifdef ERA_D_T_FMT - LANGINFO(ERA_D_T_FMT), + LANGINFO(ERA_D_T_FMT, LC_TIME), #endif #ifdef ERA_T_FMT - LANGINFO(ERA_T_FMT), + LANGINFO(ERA_T_FMT, LC_TIME), #endif #ifdef ALT_DIGITS - LANGINFO(ALT_DIGITS), + LANGINFO(ALT_DIGITS, LC_TIME), #endif #ifdef YESEXPR - LANGINFO(YESEXPR), + LANGINFO(YESEXPR, LC_MESSAGES), #endif #ifdef NOEXPR - LANGINFO(NOEXPR), + LANGINFO(NOEXPR, LC_MESSAGES), #endif #ifdef _DATE_FMT /* This is not available in all glibc versions that have CODESET. */ - LANGINFO(_DATE_FMT), + LANGINFO(_DATE_FMT, LC_TIME), #endif - {0, 0} + {0, 0, 0} }; +/* Temporary make the LC_CTYPE locale to be the same as + * the locale of the specified category. */ +static int +change_locale(int category, char **oldloc) +{ + /* Keep a copy of the LC_CTYPE locale */ + *oldloc = setlocale(LC_CTYPE, NULL); + if (!*oldloc) { + PyErr_SetString(PyExc_RuntimeError, "faild to get LC_CTYPE locale"); + return -1; + } + *oldloc = _PyMem_Strdup(*oldloc); + if (!*oldloc) { + PyErr_NoMemory(); + return -1; + } + + /* Set a new locale if it is different. */ + char *loc = setlocale(category, NULL); + if (loc == NULL || strcmp(loc, *oldloc) == 0) { + PyMem_Free(*oldloc); + *oldloc = NULL; + return 0; + } + + setlocale(LC_CTYPE, loc); + return 1; +} + +/* Restore the old LC_CTYPE locale. */ +static void +restore_locale(char *oldloc) +{ + if (oldloc != NULL) { + setlocale(LC_CTYPE, oldloc); + PyMem_Free(oldloc); + } +} + /*[clinic input] _locale.nl_langinfo @@ -602,14 +653,24 @@ _locale_nl_langinfo_impl(PyObject *module, int item) /* Check whether this is a supported constant. GNU libc sometimes returns numeric values in the char* return value, which would crash PyUnicode_FromString. */ - for (i = 0; langinfo_constants[i].name; i++) + for (i = 0; langinfo_constants[i].name; i++) { if (langinfo_constants[i].value == item) { /* Check NULL as a workaround for GNU libc's returning NULL instead of an empty string for nl_langinfo(ERA). */ const char *result = nl_langinfo(item); result = result != NULL ? result : ""; - return PyUnicode_DecodeLocale(result, NULL); + char *oldloc = NULL; + if (langinfo_constants[i].category != LC_CTYPE + && !is_all_ascii(result) + && change_locale(langinfo_constants[i].category, &oldloc) < 0) + { + return NULL; + } + PyObject *unicode = PyUnicode_DecodeLocale(result, NULL); + restore_locale(oldloc); + return unicode; } + } PyErr_SetString(PyExc_ValueError, "unsupported langinfo constant"); return NULL; } @@ -881,9 +942,9 @@ locale_clear(PyObject *module) } static void -locale_free(PyObject *module) +locale_free(void *module) { - locale_clear(module); + locale_clear((PyObject*)module); } static struct PyModuleDef _localemodule = { @@ -895,7 +956,7 @@ static struct PyModuleDef _localemodule = { _locale_slots, locale_traverse, locale_clear, - (freefunc)locale_free, + locale_free, }; PyMODINIT_FUNC diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 1f5f0215980971..f2d3b331226a7a 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -2251,6 +2251,17 @@ PySSL_dealloc(PySSLSocket *self) PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); if (self->ssl) { + // If we free the SSL socket object without having called SSL_shutdown, + // OpenSSL will invalidate the linked SSL session object. While this + // behavior is strictly RFC-compliant, it makes session reuse less + // likely and it would also break compatibility with older stdlib + // versions (which used an ugly workaround of duplicating the + // SSL_SESSION object). + // Therefore, we ensure the socket is marked as shutdown in any case. + // + // See elaborate explanation at + // https://github.com/python/cpython/pull/123249#discussion_r1766164530 + SSL_set_shutdown(self->ssl, SSL_SENT_SHUTDOWN | SSL_get_shutdown(self->ssl)); SSL_free(self->ssl); } Py_XDECREF(self->Socket); @@ -2795,48 +2806,6 @@ _ssl__SSLSocket_verify_client_post_handshake_impl(PySSLSocket *self) #endif } -static SSL_SESSION* -_ssl_session_dup(SSL_SESSION *session) { - SSL_SESSION *newsession = NULL; - int slen; - unsigned char *senc = NULL, *p; - const unsigned char *const_p; - - if (session == NULL) { - PyErr_SetString(PyExc_ValueError, "Invalid session"); - goto error; - } - - /* get length */ - slen = i2d_SSL_SESSION(session, NULL); - if (slen == 0 || slen > 0xFF00) { - PyErr_SetString(PyExc_ValueError, "i2d() failed"); - goto error; - } - if ((senc = PyMem_Malloc(slen)) == NULL) { - PyErr_NoMemory(); - goto error; - } - p = senc; - if (!i2d_SSL_SESSION(session, &p)) { - PyErr_SetString(PyExc_ValueError, "i2d() failed"); - goto error; - } - const_p = senc; - newsession = d2i_SSL_SESSION(NULL, &const_p, slen); - if (newsession == NULL) { - PyErr_SetString(PyExc_ValueError, "d2i() failed"); - goto error; - } - PyMem_Free(senc); - return newsession; - error: - if (senc != NULL) { - PyMem_Free(senc); - } - return NULL; -} - static PyObject * PySSL_get_session(PySSLSocket *self, void *closure) { /* get_session can return sessions from a server-side connection, @@ -2844,15 +2813,6 @@ PySSL_get_session(PySSLSocket *self, void *closure) { PySSLSession *pysess; SSL_SESSION *session; - /* duplicate session as workaround for session bug in OpenSSL 1.1.0, - * https://github.com/openssl/openssl/issues/1550 */ - session = SSL_get0_session(self->ssl); /* borrowed reference */ - if (session == NULL) { - Py_RETURN_NONE; - } - if ((session = _ssl_session_dup(session)) == NULL) { - return NULL; - } session = SSL_get1_session(self->ssl); if (session == NULL) { Py_RETURN_NONE; @@ -2871,11 +2831,8 @@ PySSL_get_session(PySSLSocket *self, void *closure) { } static int PySSL_set_session(PySSLSocket *self, PyObject *value, - void *closure) - { + void *closure) { PySSLSession *pysess; - SSL_SESSION *session; - int result; if (!Py_IS_TYPE(value, get_state_sock(self)->PySSLSession_Type)) { PyErr_SetString(PyExc_TypeError, "Value is not a SSLSession."); @@ -2898,14 +2855,7 @@ static int PySSL_set_session(PySSLSocket *self, PyObject *value, "Cannot set session after handshake."); return -1; } - /* duplicate session */ - if ((session = _ssl_session_dup(pysess->session)) == NULL) { - return -1; - } - result = SSL_set_session(self->ssl, session); - /* free duplicate, SSL_set_session() bumps ref count */ - SSL_SESSION_free(session); - if (result == 0) { + if (SSL_set_session(self->ssl, pysess->session) == 0) { _setSSLError(get_state_sock(self), NULL, 0, __FILE__, __LINE__); return -1; } diff --git a/Modules/_struct.c b/Modules/_struct.c index 2ae5060ba34163..4387c55b7c8848 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -12,6 +12,9 @@ #include "pycore_long.h" // _PyLong_AsByteArray() #include "pycore_moduleobject.h" // _PyModule_GetState() +#ifdef Py_HAVE_C_COMPLEX +# include "_complex.h" // complex +#endif #include // offsetof() /*[clinic input] @@ -80,6 +83,10 @@ typedef struct { char c; int x; } st_int; typedef struct { char c; long x; } st_long; typedef struct { char c; float x; } st_float; typedef struct { char c; double x; } st_double; +#ifdef Py_HAVE_C_COMPLEX +typedef struct { char c; float complex x; } st_float_complex; +typedef struct { char c; double complex x; } st_double_complex; +#endif typedef struct { char c; void *x; } st_void_p; typedef struct { char c; size_t x; } st_size_t; typedef struct { char c; _Bool x; } st_bool; @@ -89,6 +96,10 @@ typedef struct { char c; _Bool x; } st_bool; #define LONG_ALIGN (sizeof(st_long) - sizeof(long)) #define FLOAT_ALIGN (sizeof(st_float) - sizeof(float)) #define DOUBLE_ALIGN (sizeof(st_double) - sizeof(double)) +#ifdef Py_HAVE_C_COMPLEX +# define FLOAT_COMPLEX_ALIGN (sizeof(st_float_complex) - sizeof(float complex)) +# define DOUBLE_COMPLEX_ALIGN (sizeof(st_double_complex) - sizeof(double complex)) +#endif #define VOID_P_ALIGN (sizeof(st_void_p) - sizeof(void *)) #define SIZE_T_ALIGN (sizeof(st_size_t) - sizeof(size_t)) #define BOOL_ALIGN (sizeof(st_bool) - sizeof(_Bool)) @@ -407,7 +418,7 @@ static PyObject * nu_short(_structmodulestate *state, const char *p, const formatdef *f) { short x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromLong((long)x); } @@ -415,7 +426,7 @@ static PyObject * nu_ushort(_structmodulestate *state, const char *p, const formatdef *f) { unsigned short x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromLong((long)x); } @@ -423,7 +434,7 @@ static PyObject * nu_int(_structmodulestate *state, const char *p, const formatdef *f) { int x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromLong((long)x); } @@ -431,7 +442,7 @@ static PyObject * nu_uint(_structmodulestate *state, const char *p, const formatdef *f) { unsigned int x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromUnsignedLong((unsigned long)x); } @@ -439,7 +450,7 @@ static PyObject * nu_long(_structmodulestate *state, const char *p, const formatdef *f) { long x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromLong(x); } @@ -447,7 +458,7 @@ static PyObject * nu_ulong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromUnsignedLong(x); } @@ -455,7 +466,7 @@ static PyObject * nu_ssize_t(_structmodulestate *state, const char *p, const formatdef *f) { Py_ssize_t x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromSsize_t(x); } @@ -463,7 +474,7 @@ static PyObject * nu_size_t(_structmodulestate *state, const char *p, const formatdef *f) { size_t x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromSize_t(x); } @@ -471,7 +482,7 @@ static PyObject * nu_longlong(_structmodulestate *state, const char *p, const formatdef *f) { long long x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromLongLong(x); } @@ -479,7 +490,7 @@ static PyObject * nu_ulonglong(_structmodulestate *state, const char *p, const formatdef *f) { unsigned long long x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromUnsignedLongLong(x); } @@ -487,7 +498,7 @@ static PyObject * nu_bool(_structmodulestate *state, const char *p, const formatdef *f) { _Bool x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyBool_FromLong(x != 0); } @@ -506,7 +517,7 @@ static PyObject * nu_float(_structmodulestate *state, const char *p, const formatdef *f) { float x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyFloat_FromDouble((double)x); } @@ -514,15 +525,35 @@ static PyObject * nu_double(_structmodulestate *state, const char *p, const formatdef *f) { double x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyFloat_FromDouble(x); } +#ifdef Py_HAVE_C_COMPLEX +static PyObject * +nu_float_complex(_structmodulestate *state, const char *p, const formatdef *f) +{ + float complex x; + + memcpy(&x, p, sizeof(x)); + return PyComplex_FromDoubles(creal(x), cimag(x)); +} + +static PyObject * +nu_double_complex(_structmodulestate *state, const char *p, const formatdef *f) +{ + double complex x; + + memcpy(&x, p, sizeof(x)); + return PyComplex_FromDoubles(creal(x), cimag(x)); +} +#endif + static PyObject * nu_void_p(_structmodulestate *state, const char *p, const formatdef *f) { void *x; - memcpy((char *)&x, p, sizeof x); + memcpy(&x, p, sizeof x); return PyLong_FromVoidPtr(x); } @@ -587,7 +618,7 @@ np_short(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) RANGE_ERROR(state, f, 0); } y = (short)x; - memcpy(p, (char *)&y, sizeof y); + memcpy(p, &y, sizeof y); return 0; } @@ -606,7 +637,7 @@ np_ushort(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) RANGE_ERROR(state, f, 1); } y = (unsigned short)x; - memcpy(p, (char *)&y, sizeof y); + memcpy(p, &y, sizeof y); return 0; } @@ -626,7 +657,7 @@ np_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) RANGE_ERROR(state, f, 0); #endif y = (int)x; - memcpy(p, (char *)&y, sizeof y); + memcpy(p, &y, sizeof y); return 0; } @@ -646,7 +677,7 @@ np_uint(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) if (x > ((unsigned long)UINT_MAX)) RANGE_ERROR(state, f, 1); #endif - memcpy(p, (char *)&y, sizeof y); + memcpy(p, &y, sizeof y); return 0; } @@ -660,7 +691,7 @@ np_long(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) } return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -674,7 +705,7 @@ np_ulong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) } return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -688,7 +719,7 @@ np_ssize_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) } return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -702,7 +733,7 @@ np_size_t(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) } return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -720,7 +751,7 @@ np_longlong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) } return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -737,7 +768,7 @@ np_ulonglong(_structmodulestate *state, char *p, PyObject *v, const formatdef *f } return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -751,7 +782,7 @@ np_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) if (y < 0) return -1; x = y; - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -774,7 +805,7 @@ np_float(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) "required argument is not a float"); return -1; } - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -787,9 +818,61 @@ np_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) "required argument is not a float"); return -1; } - memcpy(p, (char *)&x, sizeof(double)); + memcpy(p, &x, sizeof(double)); + return 0; +} + +#ifdef Py_HAVE_C_COMPLEX +static int +np_float_complex(_structmodulestate *state, char *p, PyObject *v, + const formatdef *f) +{ + Py_complex c = PyComplex_AsCComplex(v); + float complex x = CMPLXF((float)c.real, (float)c.imag); + + if (c.real == -1 && PyErr_Occurred()) { + PyErr_SetString(state->StructError, + "required argument is not a complex"); + return -1; + } + memcpy(p, &x, sizeof(x)); + return 0; +} + +static int +np_double_complex(_structmodulestate *state, char *p, PyObject *v, + const formatdef *f) +{ + Py_complex c = PyComplex_AsCComplex(v); + double complex x = CMPLX(c.real, c.imag); + + if (c.real == -1 && PyErr_Occurred()) { + PyErr_SetString(state->StructError, + "required argument is not a complex"); + return -1; + } + memcpy(p, &x, sizeof(x)); return 0; } +#else +static int +np_complex_stub(_structmodulestate *state, char *p, PyObject *v, + const formatdef *f) +{ + PyErr_Format(state->StructError, + "'%c' format not supported on this system", + f->format); + return -1; +} +static PyObject * +nu_complex_stub(_structmodulestate *state, const char *p, const formatdef *f) +{ + PyErr_Format(state->StructError, + "'%c' format not supported on this system", + f->format); + return NULL; +} +#endif static int np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) @@ -804,7 +887,7 @@ np_void_p(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) Py_DECREF(v); if (x == NULL && PyErr_Occurred()) return -1; - memcpy(p, (char *)&x, sizeof x); + memcpy(p, &x, sizeof x); return 0; } @@ -829,6 +912,13 @@ static const formatdef native_table[] = { {'e', sizeof(short), SHORT_ALIGN, nu_halffloat, np_halffloat}, {'f', sizeof(float), FLOAT_ALIGN, nu_float, np_float}, {'d', sizeof(double), DOUBLE_ALIGN, nu_double, np_double}, +#ifdef Py_HAVE_C_COMPLEX + {'E', sizeof(float complex), FLOAT_COMPLEX_ALIGN, nu_float_complex, np_float_complex}, + {'C', sizeof(double complex), DOUBLE_COMPLEX_ALIGN, nu_double_complex, np_double_complex}, +#else + {'E', 1, 0, nu_complex_stub, np_complex_stub}, + {'C', 1, 0, nu_complex_stub, np_complex_stub}, +#endif {'P', sizeof(void *), VOID_P_ALIGN, nu_void_p, np_void_p}, {0} }; @@ -929,6 +1019,38 @@ bu_double(_structmodulestate *state, const char *p, const formatdef *f) return unpack_double(p, 0); } +#ifdef Py_HAVE_C_COMPLEX +static PyObject * +bu_float_complex(_structmodulestate *state, const char *p, const formatdef *f) +{ + double x = PyFloat_Unpack4(p, 0); + if (x == -1.0 && PyErr_Occurred()) { + return NULL; + } + double y = PyFloat_Unpack4(p + 4, 0); + if (y == -1.0 && PyErr_Occurred()) { + return NULL; + } + return PyComplex_FromDoubles(x, y); +} + +static PyObject * +bu_double_complex(_structmodulestate *state, const char *p, const formatdef *f) +{ + double x, y; + + x = PyFloat_Unpack8(p, 0); + if (x == -1.0 && PyErr_Occurred()) { + return NULL; + } + y = PyFloat_Unpack8(p + 8, 0); + if (y == -1.0 && PyErr_Occurred()) { + return NULL; + } + return PyComplex_FromDoubles(x, y); +} +#endif + static PyObject * bu_bool(_structmodulestate *state, const char *p, const formatdef *f) { @@ -1068,6 +1190,38 @@ bp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) return PyFloat_Pack8(x, p, 0); } +#ifdef Py_HAVE_C_COMPLEX +static int +bp_float_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) +{ + Py_complex x = PyComplex_AsCComplex(v); + if (x.real == -1 && PyErr_Occurred()) { + PyErr_SetString(state->StructError, + "required argument is not a complex"); + return -1; + } + if (PyFloat_Pack4(x.real, p, 0)) { + return -1; + } + return PyFloat_Pack4(x.imag, p + 4, 0); +} + +static int +bp_double_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) +{ + Py_complex x = PyComplex_AsCComplex(v); + if (x.real == -1 && PyErr_Occurred()) { + PyErr_SetString(state->StructError, + "required argument is not a complex"); + return -1; + } + if (PyFloat_Pack8(x.real, p, 0)) { + return -1; + } + return PyFloat_Pack8(x.imag, p + 8, 0); +} +#endif + static int bp_bool(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { @@ -1098,6 +1252,13 @@ static formatdef bigendian_table[] = { {'e', 2, 0, bu_halffloat, bp_halffloat}, {'f', 4, 0, bu_float, bp_float}, {'d', 8, 0, bu_double, bp_double}, +#ifdef Py_HAVE_C_COMPLEX + {'E', 8, 0, bu_float_complex, bp_float_complex}, + {'C', 16, 0, bu_double_complex, bp_double_complex}, +#else + {'E', 1, 0, nu_complex_stub, np_complex_stub}, + {'C', 1, 0, nu_complex_stub, np_complex_stub}, +#endif {0} }; @@ -1197,6 +1358,38 @@ lu_double(_structmodulestate *state, const char *p, const formatdef *f) return unpack_double(p, 1); } +#ifdef Py_HAVE_C_COMPLEX +static PyObject * +lu_float_complex(_structmodulestate *state, const char *p, const formatdef *f) +{ + double x = PyFloat_Unpack4(p, 1); + if (x == -1.0 && PyErr_Occurred()) { + return NULL; + } + double y = PyFloat_Unpack4(p + 4, 1); + if (y == -1.0 && PyErr_Occurred()) { + return NULL; + } + return PyComplex_FromDoubles(x, y); +} + +static PyObject * +lu_double_complex(_structmodulestate *state, const char *p, const formatdef *f) +{ + double x, y; + + x = PyFloat_Unpack8(p, 1); + if (x == -1.0 && PyErr_Occurred()) { + return NULL; + } + y = PyFloat_Unpack8(p + 8, 1); + if (y == -1.0 && PyErr_Occurred()) { + return NULL; + } + return PyComplex_FromDoubles(x, y); +} +#endif + static int lp_int(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) { @@ -1330,6 +1523,39 @@ lp_double(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) return PyFloat_Pack8(x, p, 1); } +#ifdef Py_HAVE_C_COMPLEX +static int +lp_float_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) +{ + Py_complex x = PyComplex_AsCComplex(v); + if (x.real == -1 && PyErr_Occurred()) { + PyErr_SetString(state->StructError, + "required argument is not a complex"); + return -1; + } + if (PyFloat_Pack4(x.real, p, 1)) { + return -1; + } + return PyFloat_Pack4(x.imag, p + 4, 1); + +} + +static int +lp_double_complex(_structmodulestate *state, char *p, PyObject *v, const formatdef *f) +{ + Py_complex x = PyComplex_AsCComplex(v); + if (x.real == -1 && PyErr_Occurred()) { + PyErr_SetString(state->StructError, + "required argument is not a complex"); + return -1; + } + if (PyFloat_Pack8(x.real, p, 1)) { + return -1; + } + return PyFloat_Pack8(x.imag, p + 8, 1); +} +#endif + static formatdef lilendian_table[] = { {'x', 1, 0, NULL}, {'b', 1, 0, nu_byte, np_byte}, @@ -1350,6 +1576,13 @@ static formatdef lilendian_table[] = { {'e', 2, 0, lu_halffloat, lp_halffloat}, {'f', 4, 0, lu_float, lp_float}, {'d', 8, 0, lu_double, lp_double}, +#ifdef Py_HAVE_C_COMPLEX + {'E', 8, 0, lu_float_complex, lp_float_complex}, + {'C', 16, 0, lu_double_complex, lp_double_complex}, +#else + {'E', 1, 0, nu_complex_stub, np_complex_stub}, + {'C', 1, 0, nu_complex_stub, np_complex_stub}, +#endif {0} }; diff --git a/Modules/_testcapi/dict.c b/Modules/_testcapi/dict.c index e80d898118daa5..307797f98f12ae 100644 --- a/Modules/_testcapi/dict.c +++ b/Modules/_testcapi/dict.c @@ -181,19 +181,6 @@ dict_popstring_null(PyObject *self, PyObject *args) RETURN_INT(PyDict_PopString(dict, key, NULL)); } -static PyObject * -dict_version(PyObject *self, PyObject *dict) -{ - if (!PyDict_Check(dict)) { - PyErr_SetString(PyExc_TypeError, "expected dict"); - return NULL; - } -_Py_COMP_DIAG_PUSH -_Py_COMP_DIAG_IGNORE_DEPR_DECLS - return PyLong_FromUnsignedLongLong(((PyDictObject *)dict)->ma_version_tag); -_Py_COMP_DIAG_POP -} - static PyMethodDef test_methods[] = { {"dict_containsstring", dict_containsstring, METH_VARARGS}, {"dict_getitemref", dict_getitemref, METH_VARARGS}, @@ -204,7 +191,6 @@ static PyMethodDef test_methods[] = { {"dict_pop_null", dict_pop_null, METH_VARARGS}, {"dict_popstring", dict_popstring, METH_VARARGS}, {"dict_popstring_null", dict_popstring_null, METH_VARARGS}, - {"dict_version", dict_version, METH_O}, {NULL}, }; diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 5966eb674cf4e5..ea26295cca49d4 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1909,25 +1909,6 @@ getitem_with_error(PyObject *self, PyObject *args) return PyObject_GetItem(map, key); } -static PyObject * -dict_get_version(PyObject *self, PyObject *args) -{ - PyDictObject *dict; - uint64_t version; - - if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict)) - return NULL; - - _Py_COMP_DIAG_PUSH - _Py_COMP_DIAG_IGNORE_DEPR_DECLS - version = dict->ma_version_tag; - _Py_COMP_DIAG_POP - - static_assert(sizeof(unsigned long long) >= sizeof(version), - "version is larger than unsigned long long"); - return PyLong_FromUnsignedLongLong((unsigned long long)version); -} - static PyObject * raise_SIGINT_then_send_None(PyObject *self, PyObject *args) @@ -3329,6 +3310,35 @@ test_critical_sections(PyObject *module, PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } +// Used by `finalize_thread_hang`. +#ifdef _POSIX_THREADS +static void finalize_thread_hang_cleanup_callback(void *Py_UNUSED(arg)) { + // Should not reach here. + Py_FatalError("pthread thread termination was triggered unexpectedly"); +} +#endif + +// Tests that finalization does not trigger pthread cleanup. +// +// Must be called with a single nullary callable function that should block +// (with GIL released) until finalization is in progress. +static PyObject * +finalize_thread_hang(PyObject *self, PyObject *callback) +{ + // WASI builds some pthread stuff but doesn't have these APIs today? +#if defined(_POSIX_THREADS) && !defined(__wasi__) + pthread_cleanup_push(finalize_thread_hang_cleanup_callback, NULL); +#endif + PyObject_CallNoArgs(callback); + // Should not reach here. + Py_FatalError("thread unexpectedly did not hang"); +#if defined(_POSIX_THREADS) && !defined(__wasi__) + pthread_cleanup_pop(0); +#endif + Py_RETURN_NONE; +} + + static PyMethodDef TestMethods[] = { {"set_errno", set_errno, METH_VARARGS}, {"test_config", test_config, METH_NOARGS}, @@ -3407,7 +3417,6 @@ static PyMethodDef TestMethods[] = { {"return_result_with_error", return_result_with_error, METH_NOARGS}, {"getitem_with_error", getitem_with_error, METH_VARARGS}, {"Py_CompileString", pycompilestring, METH_O}, - {"dict_get_version", dict_get_version, METH_VARARGS}, {"raise_SIGINT_then_send_None", raise_SIGINT_then_send_None, METH_VARARGS}, {"stack_pointer", stack_pointer, METH_NOARGS}, #ifdef W_STOPCODE @@ -3469,6 +3478,7 @@ static PyMethodDef TestMethods[] = { {"test_weakref_capi", test_weakref_capi, METH_NOARGS}, {"function_set_warning", function_set_warning, METH_NOARGS}, {"test_critical_sections", test_critical_sections, METH_NOARGS}, + {"finalize_thread_hang", finalize_thread_hang, METH_O, NULL}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_testlimitedcapi/unicode.c b/Modules/_testlimitedcapi/unicode.c index 2b70d09108a333..c7a23d5d1cbd71 100644 --- a/Modules/_testlimitedcapi/unicode.c +++ b/Modules/_testlimitedcapi/unicode.c @@ -1,7 +1,7 @@ #include "pyconfig.h" // Py_GIL_DISABLED #ifndef Py_GIL_DISABLED - // Need limited C API 3.13 to test PyUnicode_EqualToUTF8() -# define Py_LIMITED_API 0x030d0000 + // Need limited C API 3.14 to test PyUnicode_Equal() +# define Py_LIMITED_API 0x030e0000 #endif #include "parts.h" @@ -1837,6 +1837,23 @@ test_string_from_format(PyObject *self, PyObject *Py_UNUSED(ignored)) #undef CHECK_FORMAT_0 } + +/* Test PyUnicode_Equal() */ +static PyObject * +unicode_equal(PyObject *module, PyObject *args) +{ + PyObject *str1, *str2; + if (!PyArg_ParseTuple(args, "OO", &str1, &str2)) { + return NULL; + } + + NULLABLE(str1); + NULLABLE(str2); + RETURN_INT(PyUnicode_Equal(str1, str2)); +} + + + static PyMethodDef TestMethods[] = { {"codec_incrementalencoder", codec_incrementalencoder, METH_VARARGS}, {"codec_incrementaldecoder", codec_incrementaldecoder, METH_VARARGS}, @@ -1924,6 +1941,7 @@ static PyMethodDef TestMethods[] = { {"unicode_format", unicode_format, METH_VARARGS}, {"unicode_contains", unicode_contains, METH_VARARGS}, {"unicode_isidentifier", unicode_isidentifier, METH_O}, + {"unicode_equal", unicode_equal, METH_VARARGS}, {NULL}, }; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index b3ed8e7bc56b9e..9617f9cafe76ff 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -599,8 +599,9 @@ PyThreadHandleObject_traverse(PyThreadHandleObject *self, visitproc visit, } static void -PyThreadHandleObject_dealloc(PyThreadHandleObject *self) +PyThreadHandleObject_dealloc(PyObject *op) { + PyThreadHandleObject *self = (PyThreadHandleObject*)op; PyObject_GC_UnTrack(self); PyTypeObject *tp = Py_TYPE(self); ThreadHandle_decref(self->handle); @@ -609,23 +610,26 @@ PyThreadHandleObject_dealloc(PyThreadHandleObject *self) } static PyObject * -PyThreadHandleObject_repr(PyThreadHandleObject *self) +PyThreadHandleObject_repr(PyObject *op) { + PyThreadHandleObject *self = (PyThreadHandleObject*)op; PyThread_ident_t ident = ThreadHandle_ident(self->handle); return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">", Py_TYPE(self)->tp_name, ident); } static PyObject * -PyThreadHandleObject_get_ident(PyThreadHandleObject *self, - PyObject *Py_UNUSED(ignored)) +PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(ignored)) { + PyThreadHandleObject *self = (PyThreadHandleObject*)op; return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle)); } static PyObject * -PyThreadHandleObject_join(PyThreadHandleObject *self, PyObject *args) +PyThreadHandleObject_join(PyObject *op, PyObject *args) { + PyThreadHandleObject *self = (PyThreadHandleObject*)op; + PyObject *timeout_obj = NULL; if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) { return NULL; @@ -646,9 +650,9 @@ PyThreadHandleObject_join(PyThreadHandleObject *self, PyObject *args) } static PyObject * -PyThreadHandleObject_is_done(PyThreadHandleObject *self, - PyObject *Py_UNUSED(ignored)) +PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyThreadHandleObject *self = (PyThreadHandleObject*)op; if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) { Py_RETURN_TRUE; } @@ -658,9 +662,9 @@ PyThreadHandleObject_is_done(PyThreadHandleObject *self, } static PyObject * -PyThreadHandleObject_set_done(PyThreadHandleObject *self, - PyObject *Py_UNUSED(ignored)) +PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(ignored)) { + PyThreadHandleObject *self = (PyThreadHandleObject*)op; if (ThreadHandle_set_done(self->handle) < 0) { return NULL; } @@ -668,20 +672,20 @@ PyThreadHandleObject_set_done(PyThreadHandleObject *self, } static PyGetSetDef ThreadHandle_getsetlist[] = { - {"ident", (getter)PyThreadHandleObject_get_ident, NULL, NULL}, + {"ident", PyThreadHandleObject_get_ident, NULL, NULL}, {0}, }; static PyMethodDef ThreadHandle_methods[] = { - {"join", (PyCFunction)PyThreadHandleObject_join, METH_VARARGS, NULL}, - {"_set_done", (PyCFunction)PyThreadHandleObject_set_done, METH_NOARGS, NULL}, - {"is_done", (PyCFunction)PyThreadHandleObject_is_done, METH_NOARGS, NULL}, + {"join", PyThreadHandleObject_join, METH_VARARGS, NULL}, + {"_set_done", PyThreadHandleObject_set_done, METH_NOARGS, NULL}, + {"is_done", PyThreadHandleObject_is_done, METH_NOARGS, NULL}, {0, 0} }; static PyType_Slot ThreadHandle_Type_slots[] = { - {Py_tp_dealloc, (destructor)PyThreadHandleObject_dealloc}, - {Py_tp_repr, (reprfunc)PyThreadHandleObject_repr}, + {Py_tp_dealloc, PyThreadHandleObject_dealloc}, + {Py_tp_repr, PyThreadHandleObject_repr}, {Py_tp_getset, ThreadHandle_getsetlist}, {Py_tp_traverse, PyThreadHandleObject_traverse}, {Py_tp_methods, ThreadHandle_methods}, @@ -701,31 +705,22 @@ static PyType_Spec ThreadHandle_Type_spec = { typedef struct { PyObject_HEAD - PyThread_type_lock lock_lock; - PyObject *in_weakreflist; - char locked; /* for sanity checking */ + PyMutex lock; } lockobject; static int -lock_traverse(lockobject *self, visitproc visit, void *arg) +lock_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); return 0; } static void -lock_dealloc(lockobject *self) +lock_dealloc(PyObject *op) { + lockobject *self = (lockobject*)op; PyObject_GC_UnTrack(self); - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *) self); - } - if (self->lock_lock != NULL) { - /* Unlock the lock so it's safe to free it */ - if (self->locked) - PyThread_release_lock(self->lock_lock); - PyThread_free_lock(self->lock_lock); - } + PyObject_ClearWeakRefs((PyObject *) self); PyTypeObject *tp = Py_TYPE(self); tp->tp_free((PyObject*)self); Py_DECREF(tp); @@ -784,19 +779,21 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds, } static PyObject * -lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds) +lock_PyThread_acquire_lock(PyObject *op, PyObject *args, PyObject *kwds) { + lockobject *self = (lockobject*)op; + PyTime_t timeout; - if (lock_acquire_parse_args(args, kwds, &timeout) < 0) + if (lock_acquire_parse_args(args, kwds, &timeout) < 0) { return NULL; + } - PyLockStatus r = acquire_timed(self->lock_lock, timeout); + PyLockStatus r = _PyMutex_LockTimed(&self->lock, timeout, + _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH); if (r == PY_LOCK_INTR) { return NULL; } - if (r == PY_LOCK_ACQUIRED) - self->locked = 1; return PyBool_FromLong(r == PY_LOCK_ACQUIRED); } @@ -824,16 +821,15 @@ PyDoc_STRVAR(enter_doc, Lock the lock."); static PyObject * -lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored)) +lock_PyThread_release_lock(PyObject *op, PyObject *Py_UNUSED(ignored)) { + lockobject *self = (lockobject*)op; /* Sanity check: the lock must be locked */ - if (!self->locked) { + if (_PyMutex_TryUnlock(&self->lock) < 0) { PyErr_SetString(ThreadError, "release unlocked lock"); return NULL; } - self->locked = 0; - PyThread_release_lock(self->lock_lock); Py_RETURN_NONE; } @@ -858,9 +854,10 @@ PyDoc_STRVAR(lock_exit_doc, Release the lock."); static PyObject * -lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored)) +lock_locked_lock(PyObject *op, PyObject *Py_UNUSED(ignored)) { - return PyBool_FromLong((long)self->locked); + lockobject *self = (lockobject*)op; + return PyBool_FromLong(PyMutex_IsLocked(&self->lock)); } PyDoc_STRVAR(locked_doc, @@ -876,23 +873,19 @@ PyDoc_STRVAR(locked_lock_doc, An obsolete synonym of locked()."); static PyObject * -lock_repr(lockobject *self) +lock_repr(PyObject *op) { + lockobject *self = (lockobject*)op; return PyUnicode_FromFormat("<%s %s object at %p>", - self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self); + PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self); } #ifdef HAVE_FORK static PyObject * -lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args)) +lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(args)) { - if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) { - PyErr_SetString(ThreadError, "failed to reinitialize lock at fork"); - return NULL; - } - - self->locked = 0; - + lockobject *self = (lockobject *)op; + _PyMutex_at_fork_reinit(&self->lock); Py_RETURN_NONE; } #endif /* HAVE_FORK */ @@ -924,20 +917,20 @@ static PyMethodDef lock_methods[] = { METH_VARARGS | METH_KEYWORDS, acquire_lock_doc}, {"acquire", _PyCFunction_CAST(lock_PyThread_acquire_lock), METH_VARARGS | METH_KEYWORDS, acquire_doc}, - {"release_lock", (PyCFunction)lock_PyThread_release_lock, + {"release_lock", lock_PyThread_release_lock, METH_NOARGS, release_lock_doc}, - {"release", (PyCFunction)lock_PyThread_release_lock, + {"release", lock_PyThread_release_lock, METH_NOARGS, release_doc}, - {"locked_lock", (PyCFunction)lock_locked_lock, + {"locked_lock", lock_locked_lock, METH_NOARGS, locked_lock_doc}, - {"locked", (PyCFunction)lock_locked_lock, + {"locked", lock_locked_lock, METH_NOARGS, locked_doc}, {"__enter__", _PyCFunction_CAST(lock_PyThread_acquire_lock), METH_VARARGS | METH_KEYWORDS, enter_doc}, - {"__exit__", (PyCFunction)lock_PyThread_release_lock, + {"__exit__", lock_PyThread_release_lock, METH_VARARGS, lock_exit_doc}, #ifdef HAVE_FORK - {"_at_fork_reinit", (PyCFunction)lock__at_fork_reinit, + {"_at_fork_reinit", lock__at_fork_reinit, METH_NOARGS, NULL}, #endif {NULL, NULL} /* sentinel */ @@ -958,18 +951,12 @@ A lock is not owned by the thread that locked it; another thread may\n\ unlock it. A thread attempting to lock a lock that it has already locked\n\ will block until another thread unlocks it. Deadlocks may ensue."); -static PyMemberDef lock_type_members[] = { - {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(lockobject, in_weakreflist), Py_READONLY}, - {NULL}, -}; - static PyType_Slot lock_type_slots[] = { - {Py_tp_dealloc, (destructor)lock_dealloc}, - {Py_tp_repr, (reprfunc)lock_repr}, + {Py_tp_dealloc, lock_dealloc}, + {Py_tp_repr, lock_repr}, {Py_tp_doc, (void *)lock_doc}, {Py_tp_methods, lock_methods}, {Py_tp_traverse, lock_traverse}, - {Py_tp_members, lock_type_members}, {Py_tp_new, lock_new}, {0, 0} }; @@ -978,7 +965,7 @@ static PyType_Spec lock_type_spec = { .name = "_thread.lock", .basicsize = sizeof(lockobject), .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_IMMUTABLETYPE), + Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF), .slots = lock_type_slots, }; @@ -1001,8 +988,9 @@ rlock_traverse(rlockobject *self, visitproc visit, void *arg) static void -rlock_dealloc(rlockobject *self) +rlock_dealloc(PyObject *op) { + rlockobject *self = (rlockobject*)op; PyObject_GC_UnTrack(self); if (self->in_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); @@ -1029,8 +1017,9 @@ rlock_is_owned_by(rlockobject *self, PyThread_ident_t tid) } static PyObject * -rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds) +rlock_acquire(PyObject *op, PyObject *args, PyObject *kwds) { + rlockobject *self = (rlockobject*)op; PyTime_t timeout; PyThread_ident_t tid; PyLockStatus r = PY_LOCK_ACQUIRED; @@ -1086,8 +1075,9 @@ PyDoc_STRVAR(rlock_enter_doc, Lock the lock."); static PyObject * -rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored)) +rlock_release(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rlockobject *self = (rlockobject*)op; PyThread_ident_t tid = PyThread_get_thread_ident_ex(); if (!rlock_is_owned_by(self, tid)) { @@ -1122,8 +1112,9 @@ PyDoc_STRVAR(rlock_exit_doc, Release the lock."); static PyObject * -rlock_acquire_restore(rlockobject *self, PyObject *args) +rlock_acquire_restore(PyObject *op, PyObject *args) { + rlockobject *self = (rlockobject*)op; PyThread_ident_t owner; unsigned long count; int r = 1; @@ -1154,8 +1145,9 @@ PyDoc_STRVAR(rlock_acquire_restore_doc, For internal use by `threading.Condition`."); static PyObject * -rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored)) +rlock_release_save(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rlockobject *self = (rlockobject*)op; PyThread_ident_t owner; unsigned long count; @@ -1180,8 +1172,9 @@ PyDoc_STRVAR(rlock_release_save_doc, For internal use by `threading.Condition`."); static PyObject * -rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored)) +rlock_recursion_count(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rlockobject *self = (rlockobject*)op; PyThread_ident_t tid = PyThread_get_thread_ident_ex(); PyThread_ident_t owner = _Py_atomic_load_ullong_relaxed(&self->rlock_owner); @@ -1195,8 +1188,9 @@ PyDoc_STRVAR(rlock_recursion_count_doc, For internal use by reentrancy checks."); static PyObject * -rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored)) +rlock_is_owned(PyObject *op, PyObject *Py_UNUSED(ignored)) { + rlockobject *self = (rlockobject*)op; PyThread_ident_t tid = PyThread_get_thread_ident_ex(); if (rlock_is_owned_by(self, tid)) { @@ -1232,8 +1226,9 @@ rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } static PyObject * -rlock_repr(rlockobject *self) +rlock_repr(PyObject *op) { + rlockobject *self = (rlockobject*)op; PyThread_ident_t owner = _Py_atomic_load_ullong_relaxed(&self->rlock_owner); return PyUnicode_FromFormat( @@ -1264,19 +1259,19 @@ rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args)) static PyMethodDef rlock_methods[] = { {"acquire", _PyCFunction_CAST(rlock_acquire), METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc}, - {"release", (PyCFunction)rlock_release, + {"release", rlock_release, METH_NOARGS, rlock_release_doc}, - {"_is_owned", (PyCFunction)rlock_is_owned, + {"_is_owned", rlock_is_owned, METH_NOARGS, rlock_is_owned_doc}, - {"_acquire_restore", (PyCFunction)rlock_acquire_restore, + {"_acquire_restore", rlock_acquire_restore, METH_VARARGS, rlock_acquire_restore_doc}, - {"_release_save", (PyCFunction)rlock_release_save, + {"_release_save", rlock_release_save, METH_NOARGS, rlock_release_save_doc}, - {"_recursion_count", (PyCFunction)rlock_recursion_count, + {"_recursion_count", rlock_recursion_count, METH_NOARGS, rlock_recursion_count_doc}, {"__enter__", _PyCFunction_CAST(rlock_acquire), METH_VARARGS | METH_KEYWORDS, rlock_enter_doc}, - {"__exit__", (PyCFunction)rlock_release, + {"__exit__", rlock_release, METH_VARARGS, rlock_exit_doc}, #ifdef HAVE_FORK {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit, @@ -1292,8 +1287,8 @@ static PyMemberDef rlock_type_members[] = { }; static PyType_Slot rlock_type_slots[] = { - {Py_tp_dealloc, (destructor)rlock_dealloc}, - {Py_tp_repr, (reprfunc)rlock_repr}, + {Py_tp_dealloc, rlock_dealloc}, + {Py_tp_repr, rlock_repr}, {Py_tp_methods, rlock_methods}, {Py_tp_alloc, PyType_GenericAlloc}, {Py_tp_new, rlock_new}, @@ -1320,16 +1315,7 @@ newlockobject(PyObject *module) if (self == NULL) { return NULL; } - - self->lock_lock = PyThread_allocate_lock(); - self->locked = 0; - self->in_weakreflist = NULL; - - if (self->lock_lock == NULL) { - Py_DECREF(self); - PyErr_SetString(ThreadError, "can't allocate lock"); - return NULL; - } + self->lock = (PyMutex){0}; return self; } @@ -1392,8 +1378,9 @@ typedef struct { } localdummyobject; static void -localdummy_dealloc(localdummyobject *self) +localdummy_dealloc(PyObject *op) { + localdummyobject *self = (localdummyobject*)op; if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); PyTypeObject *tp = Py_TYPE(self); @@ -1407,7 +1394,7 @@ static PyMemberDef local_dummy_type_members[] = { }; static PyType_Slot local_dummy_type_slots[] = { - {Py_tp_dealloc, (destructor)localdummy_dealloc}, + {Py_tp_dealloc, localdummy_dealloc}, {Py_tp_doc, "Thread-local dummy"}, {Py_tp_members, local_dummy_type_members}, {0, 0} diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index f7e0aaf7b23649..8399c5620f125b 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -1389,12 +1389,12 @@ _curses_window_overlay(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overlay", &PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overlay", clinic_state()->window_type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", clinic_state()->window_type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -1448,12 +1448,12 @@ _curses_window_overwrite(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overwrite", &PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overwrite", clinic_state()->window_type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", clinic_state()->window_type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -3693,25 +3693,55 @@ PyDoc_STRVAR(_curses_resizeterm__doc__, {"resizeterm", _PyCFunction_CAST(_curses_resizeterm), METH_FASTCALL, _curses_resizeterm__doc__}, static PyObject * -_curses_resizeterm_impl(PyObject *module, int nlines, int ncols); +_curses_resizeterm_impl(PyObject *module, short nlines, short ncols); static PyObject * _curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - int nlines; - int ncols; + short nlines; + short ncols; if (!_PyArg_CheckPositional("resizeterm", nargs, 2, 2)) { goto exit; } - nlines = PyLong_AsInt(args[0]); - if (nlines == -1 && PyErr_Occurred()) { - goto exit; + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + nlines = (short) ival; + } } - ncols = PyLong_AsInt(args[1]); - if (ncols == -1 && PyErr_Occurred()) { - goto exit; + { + long ival = PyLong_AsLong(args[1]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + ncols = (short) ival; + } } return_value = _curses_resizeterm_impl(module, nlines, ncols); @@ -3744,25 +3774,55 @@ PyDoc_STRVAR(_curses_resize_term__doc__, {"resize_term", _PyCFunction_CAST(_curses_resize_term), METH_FASTCALL, _curses_resize_term__doc__}, static PyObject * -_curses_resize_term_impl(PyObject *module, int nlines, int ncols); +_curses_resize_term_impl(PyObject *module, short nlines, short ncols); static PyObject * _curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - int nlines; - int ncols; + short nlines; + short ncols; if (!_PyArg_CheckPositional("resize_term", nargs, 2, 2)) { goto exit; } - nlines = PyLong_AsInt(args[0]); - if (nlines == -1 && PyErr_Occurred()) { - goto exit; + { + long ival = PyLong_AsLong(args[0]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + nlines = (short) ival; + } } - ncols = PyLong_AsInt(args[1]); - if (ncols == -1 && PyErr_Occurred()) { - goto exit; + { + long ival = PyLong_AsLong(args[1]); + if (ival == -1 && PyErr_Occurred()) { + goto exit; + } + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + goto exit; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + goto exit; + } + else { + ncols = (short) ival; + } } return_value = _curses_resize_term_impl(module, nlines, ncols); @@ -4318,4 +4378,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=96887782374f070a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cd1273354b08948f input=a9049054013a1b77]*/ diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index a80e4670665a22..fd2a85a3fe0a61 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -42,15 +42,16 @@ _getbytevalue(PyObject* arg, int *value) } static int -bytearray_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags) +bytearray_getbuffer(PyObject *self, Py_buffer *view, int flags) { - void *ptr; + PyByteArrayObject *obj = _PyByteArray_CAST(self); if (view == NULL) { PyErr_SetString(PyExc_BufferError, "bytearray_getbuffer: view==NULL argument is obsolete"); return -1; } - ptr = (void *) PyByteArray_AS_STRING(obj); + + void *ptr = (void *) PyByteArray_AS_STRING(obj); /* cannot fail if view != NULL and readonly == 0 */ (void)PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags); obj->ob_exports++; @@ -58,8 +59,9 @@ bytearray_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags) } static void -bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view) +bytearray_releasebuffer(PyObject *self, Py_buffer *view) { + PyByteArrayObject *obj = _PyByteArray_CAST(self); obj->ob_exports--; assert(obj->ob_exports >= 0); } @@ -286,46 +288,53 @@ PyByteArray_Concat(PyObject *a, PyObject *b) /* Functions stuffed into the type object */ static Py_ssize_t -bytearray_length(PyByteArrayObject *self) +bytearray_length(PyObject *op) { + PyByteArrayObject *self = _PyByteArray_CAST(op); return Py_SIZE(self); } static PyObject * -bytearray_iconcat(PyByteArrayObject *self, PyObject *other) +bytearray_iconcat(PyObject *op, PyObject *other) { - Py_ssize_t size; - Py_buffer vo; + PyByteArrayObject *self = _PyByteArray_CAST(op); + Py_buffer vo; if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) { PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name); return NULL; } - size = Py_SIZE(self); + Py_ssize_t size = Py_SIZE(self); if (size > PY_SSIZE_T_MAX - vo.len) { PyBuffer_Release(&vo); return PyErr_NoMemory(); } + if (PyByteArray_Resize((PyObject *)self, size + vo.len) < 0) { PyBuffer_Release(&vo); return NULL; } + memcpy(PyByteArray_AS_STRING(self) + size, vo.buf, vo.len); PyBuffer_Release(&vo); return Py_NewRef(self); } static PyObject * -bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count) +bytearray_repeat(PyObject *op, Py_ssize_t count) { - if (count < 0) + PyByteArrayObject *self = _PyByteArray_CAST(op); + if (count < 0) { count = 0; + } const Py_ssize_t mysize = Py_SIZE(self); - if (count > 0 && mysize > PY_SSIZE_T_MAX / count) + if (count > 0 && mysize > PY_SSIZE_T_MAX / count) { return PyErr_NoMemory(); + } Py_ssize_t size = mysize * count; + PyByteArrayObject* result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size); const char* buf = PyByteArray_AS_STRING(self); if (result != NULL && size != 0) { @@ -335,20 +344,24 @@ bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count) } static PyObject * -bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count) +bytearray_irepeat(PyObject *op, Py_ssize_t count) { - if (count < 0) + PyByteArrayObject *self = _PyByteArray_CAST(op); + if (count < 0) { count = 0; + } else if (count == 1) { return Py_NewRef(self); } const Py_ssize_t mysize = Py_SIZE(self); - if (count > 0 && mysize > PY_SSIZE_T_MAX / count) + if (count > 0 && mysize > PY_SSIZE_T_MAX / count) { return PyErr_NoMemory(); + } const Py_ssize_t size = mysize * count; - if (PyByteArray_Resize((PyObject *)self, size) < 0) + if (PyByteArray_Resize((PyObject *)self, size) < 0) { return NULL; + } char* buf = PyByteArray_AS_STRING(self); _PyBytes_Repeat(buf, size, buf, mysize); @@ -357,8 +370,9 @@ bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count) } static PyObject * -bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i) +bytearray_getitem(PyObject *op, Py_ssize_t i) { + PyByteArrayObject *self = _PyByteArray_CAST(op); if (i < 0 || i >= Py_SIZE(self)) { PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); return NULL; @@ -367,8 +381,9 @@ bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i) } static PyObject * -bytearray_subscript(PyByteArrayObject *self, PyObject *index) +bytearray_subscript(PyObject *op, PyObject *index) { + PyByteArrayObject *self = _PyByteArray_CAST(op); if (_PyIndex_Check(index)) { Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); @@ -559,12 +574,13 @@ bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi, } static int -bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) +bytearray_setitem(PyObject *op, Py_ssize_t i, PyObject *value) { - int ival = -1; + PyByteArrayObject *self = _PyByteArray_CAST(op); // GH-91153: We need to do this *before* the size check, in case value has a // nasty __index__ method that changes the size of the bytearray: + int ival = -1; if (value && !_getbytevalue(value, &ival)) { return -1; } @@ -588,11 +604,11 @@ bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) } static int -bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *values) +bytearray_ass_subscript(PyObject *op, PyObject *index, PyObject *values) { - Py_ssize_t start, stop, step, slicelen, needed; - char *buf, *bytes; - buf = PyByteArray_AS_STRING(self); + PyByteArrayObject *self = _PyByteArray_CAST(op); + Py_ssize_t start, stop, step, slicelen; + char *buf = PyByteArray_AS_STRING(self); if (_PyIndex_Check(index)) { Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); @@ -645,6 +661,8 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu return -1; } + char *bytes; + Py_ssize_t needed; if (values == NULL) { bytes = NULL; needed = 0; @@ -661,7 +679,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu values = PyByteArray_FromObject(values); if (values == NULL) return -1; - err = bytearray_ass_subscript(self, index, values); + err = bytearray_ass_subscript((PyObject*)self, index, values); Py_DECREF(values); return err; } @@ -670,10 +688,14 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu bytes = PyByteArray_AS_STRING(values); needed = Py_SIZE(values); } + /* Make sure b[5:2] = ... inserts before 5, not before 2. */ if ((step < 0 && start < stop) || (step > 0 && start > stop)) + { stop = start; + } + if (step == 1) { return bytearray_setslice_linear(self, start, stop, bytes, needed); } @@ -785,7 +807,7 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg, if (encoded == NULL) return -1; assert(PyBytes_Check(encoded)); - new = bytearray_iconcat(self, encoded); + new = bytearray_iconcat((PyObject*)self, encoded); Py_DECREF(encoded); if (new == NULL) return -1; @@ -926,8 +948,9 @@ bytearray___init___impl(PyByteArrayObject *self, PyObject *arg, /* Mostly copied from string_repr, but without the "smart quote" functionality. */ static PyObject * -bytearray_repr(PyByteArrayObject *self) +bytearray_repr(PyObject *op) { + PyByteArrayObject *self = _PyByteArray_CAST(op); const char *className = _PyType_Name(Py_TYPE(self)); const char *quote_prefix = "(b"; const char *quote_postfix = ")"; @@ -1021,7 +1044,7 @@ bytearray_str(PyObject *op) return NULL; } } - return bytearray_repr((PyByteArrayObject*)op); + return bytearray_repr(op); } static PyObject * @@ -1080,8 +1103,9 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op) } static void -bytearray_dealloc(PyByteArrayObject *self) +bytearray_dealloc(PyObject *op) { + PyByteArrayObject *self = _PyByteArray_CAST(op); if (self->ob_exports > 0) { PyErr_SetString(PyExc_SystemError, "deallocated bytearray object has exported buffers"); @@ -1244,7 +1268,9 @@ bytearray_rindex_impl(PyByteArrayObject *self, PyObject *sub, static int bytearray_contains(PyObject *self, PyObject *arg) { - return _Py_bytes_contains(PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), arg); + return _Py_bytes_contains(PyByteArray_AS_STRING(self), + PyByteArray_GET_SIZE(self), + arg); } /*[clinic input] @@ -2262,31 +2288,30 @@ bytearray_sizeof_impl(PyByteArrayObject *self) } static PySequenceMethods bytearray_as_sequence = { - (lenfunc)bytearray_length, /* sq_length */ - (binaryfunc)PyByteArray_Concat, /* sq_concat */ - (ssizeargfunc)bytearray_repeat, /* sq_repeat */ - (ssizeargfunc)bytearray_getitem, /* sq_item */ + bytearray_length, /* sq_length */ + PyByteArray_Concat, /* sq_concat */ + bytearray_repeat, /* sq_repeat */ + bytearray_getitem, /* sq_item */ 0, /* sq_slice */ - (ssizeobjargproc)bytearray_setitem, /* sq_ass_item */ + bytearray_setitem, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)bytearray_contains, /* sq_contains */ - (binaryfunc)bytearray_iconcat, /* sq_inplace_concat */ - (ssizeargfunc)bytearray_irepeat, /* sq_inplace_repeat */ + bytearray_contains, /* sq_contains */ + bytearray_iconcat, /* sq_inplace_concat */ + bytearray_irepeat, /* sq_inplace_repeat */ }; static PyMappingMethods bytearray_as_mapping = { - (lenfunc)bytearray_length, - (binaryfunc)bytearray_subscript, - (objobjargproc)bytearray_ass_subscript, + bytearray_length, + bytearray_subscript, + bytearray_ass_subscript, }; static PyBufferProcs bytearray_as_buffer = { - (getbufferproc)bytearray_getbuffer, - (releasebufferproc)bytearray_releasebuffer, + bytearray_getbuffer, + bytearray_releasebuffer, }; -static PyMethodDef -bytearray_methods[] = { +static PyMethodDef bytearray_methods[] = { {"__alloc__", (PyCFunction)bytearray_alloc, METH_NOARGS, alloc_doc}, BYTEARRAY_REDUCE_METHODDEF BYTEARRAY_REDUCE_EX_METHODDEF @@ -2391,12 +2416,12 @@ PyTypeObject PyByteArray_Type = { "bytearray", sizeof(PyByteArrayObject), 0, - (destructor)bytearray_dealloc, /* tp_dealloc */ + bytearray_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)bytearray_repr, /* tp_repr */ + bytearray_repr, /* tp_repr */ &bytearray_as_number, /* tp_as_number */ &bytearray_as_sequence, /* tp_as_sequence */ &bytearray_as_mapping, /* tp_as_mapping */ @@ -2411,7 +2436,7 @@ PyTypeObject PyByteArray_Type = { bytearray_doc, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ - (richcmpfunc)bytearray_richcompare, /* tp_richcompare */ + bytearray_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ bytearray_iter, /* tp_iter */ 0, /* tp_iternext */ diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index ba6636808d90e0..58a4feed351707 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1405,8 +1405,9 @@ bytes_str(PyObject *op) } static Py_ssize_t -bytes_length(PyBytesObject *a) +bytes_length(PyObject *self) { + PyBytesObject *a = _PyBytes_CAST(self); return Py_SIZE(a); } @@ -1456,11 +1457,9 @@ bytes_concat(PyObject *a, PyObject *b) } static PyObject * -bytes_repeat(PyBytesObject *a, Py_ssize_t n) +bytes_repeat(PyObject *self, Py_ssize_t n) { - Py_ssize_t size; - PyBytesObject *op; - size_t nbytes; + PyBytesObject *a = _PyBytes_CAST(self); if (n < 0) n = 0; /* watch out for overflows: the size can overflow int, @@ -1471,17 +1470,17 @@ bytes_repeat(PyBytesObject *a, Py_ssize_t n) "repeated bytes are too long"); return NULL; } - size = Py_SIZE(a) * n; + Py_ssize_t size = Py_SIZE(a) * n; if (size == Py_SIZE(a) && PyBytes_CheckExact(a)) { return Py_NewRef(a); } - nbytes = (size_t)size; + size_t nbytes = (size_t)size; if (nbytes + PyBytesObject_SIZE <= nbytes) { PyErr_SetString(PyExc_OverflowError, "repeated bytes are too long"); return NULL; } - op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + nbytes); + PyBytesObject *op = PyObject_Malloc(PyBytesObject_SIZE + nbytes); if (op == NULL) { return PyErr_NoMemory(); } @@ -1504,8 +1503,9 @@ bytes_contains(PyObject *self, PyObject *arg) } static PyObject * -bytes_item(PyBytesObject *a, Py_ssize_t i) +bytes_item(PyObject *self, Py_ssize_t i) { + PyBytesObject *a = _PyBytes_CAST(self); if (i < 0 || i >= Py_SIZE(a)) { PyErr_SetString(PyExc_IndexError, "index out of range"); return NULL; @@ -1531,21 +1531,17 @@ bytes_compare_eq(PyBytesObject *a, PyBytesObject *b) } static PyObject* -bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) +bytes_richcompare(PyObject *aa, PyObject *bb, int op) { - int c; - Py_ssize_t len_a, len_b; - Py_ssize_t min_len; - /* Make sure both arguments are strings. */ - if (!(PyBytes_Check(a) && PyBytes_Check(b))) { + if (!(PyBytes_Check(aa) && PyBytes_Check(bb))) { if (_Py_GetConfig()->bytes_warning && (op == Py_EQ || op == Py_NE)) { - if (PyUnicode_Check(a) || PyUnicode_Check(b)) { + if (PyUnicode_Check(aa) || PyUnicode_Check(bb)) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytes and string", 1)) return NULL; } - if (PyLong_Check(a) || PyLong_Check(b)) { + if (PyLong_Check(aa) || PyLong_Check(bb)) { if (PyErr_WarnEx(PyExc_BytesWarning, "Comparison between bytes and int", 1)) return NULL; @@ -1553,7 +1549,10 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) } Py_RETURN_NOTIMPLEMENTED; } - else if (a == b) { + + PyBytesObject *a = _PyBytes_CAST(aa); + PyBytesObject *b = _PyBytes_CAST(bb); + if (a == b) { switch (op) { case Py_EQ: case Py_LE: @@ -1575,25 +1574,29 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) return PyBool_FromLong(eq); } else { - len_a = Py_SIZE(a); - len_b = Py_SIZE(b); - min_len = Py_MIN(len_a, len_b); + Py_ssize_t len_a = Py_SIZE(a); + Py_ssize_t len_b = Py_SIZE(b); + Py_ssize_t min_len = Py_MIN(len_a, len_b); + int c; if (min_len > 0) { c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); if (c == 0) c = memcmp(a->ob_sval, b->ob_sval, min_len); } - else + else { c = 0; - if (c != 0) + } + if (c != 0) { Py_RETURN_RICHCOMPARE(c, 0, op); + } Py_RETURN_RICHCOMPARE(len_a, len_b, op); } } static Py_hash_t -bytes_hash(PyBytesObject *a) +bytes_hash(PyObject *self) { + PyBytesObject *a = _PyBytes_CAST(self); _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS if (a->ob_shash == -1) { @@ -1605,8 +1608,9 @@ _Py_COMP_DIAG_POP } static PyObject* -bytes_subscript(PyBytesObject* self, PyObject* item) +bytes_subscript(PyObject *op, PyObject* item) { + PyBytesObject *self = _PyBytes_CAST(op); if (_PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) @@ -1670,31 +1674,32 @@ bytes_subscript(PyBytesObject* self, PyObject* item) } static int -bytes_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags) +bytes_buffer_getbuffer(PyObject *op, Py_buffer *view, int flags) { + PyBytesObject *self = _PyBytes_CAST(op); return PyBuffer_FillInfo(view, (PyObject*)self, (void *)self->ob_sval, Py_SIZE(self), 1, flags); } static PySequenceMethods bytes_as_sequence = { - (lenfunc)bytes_length, /*sq_length*/ - (binaryfunc)bytes_concat, /*sq_concat*/ - (ssizeargfunc)bytes_repeat, /*sq_repeat*/ - (ssizeargfunc)bytes_item, /*sq_item*/ + bytes_length, /*sq_length*/ + bytes_concat, /*sq_concat*/ + bytes_repeat, /*sq_repeat*/ + bytes_item, /*sq_item*/ 0, /*sq_slice*/ 0, /*sq_ass_item*/ 0, /*sq_ass_slice*/ - (objobjproc)bytes_contains /*sq_contains*/ + bytes_contains /*sq_contains*/ }; static PyMappingMethods bytes_as_mapping = { - (lenfunc)bytes_length, - (binaryfunc)bytes_subscript, + bytes_length, + bytes_subscript, 0, }; static PyBufferProcs bytes_as_buffer = { - (getbufferproc)bytes_buffer_getbuffer, + bytes_buffer_getbuffer, NULL, }; @@ -3043,11 +3048,11 @@ PyTypeObject PyBytes_Type = { 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)bytes_repr, /* tp_repr */ + bytes_repr, /* tp_repr */ &bytes_as_number, /* tp_as_number */ &bytes_as_sequence, /* tp_as_sequence */ &bytes_as_mapping, /* tp_as_mapping */ - (hashfunc)bytes_hash, /* tp_hash */ + bytes_hash, /* tp_hash */ 0, /* tp_call */ bytes_str, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ diff --git a/Objects/classobject.c b/Objects/classobject.c index 69a7d5f046e30d..775894ad5a7166 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -10,6 +10,7 @@ #include "clinic/classobject.c.h" +#define _PyMethodObject_CAST(op) _Py_CAST(PyMethodObject*, (op)) #define TP_DESCR_GET(t) ((t)->tp_descr_get) /*[clinic input] @@ -166,13 +167,14 @@ static PyMemberDef method_memberlist[] = { should only be used for the class, not for instances */ static PyObject * -method_get_doc(PyMethodObject *im, void *context) +method_get_doc(PyObject *self, void *context) { + PyMethodObject *im = _PyMethodObject_CAST(self); return PyObject_GetAttr(im->im_func, &_Py_ID(__doc__)); } static PyGetSetDef method_getset[] = { - {"__doc__", (getter)method_get_doc, NULL, NULL}, + {"__doc__", method_get_doc, NULL, NULL}, {0} }; @@ -235,8 +237,9 @@ method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance) } static void -method_dealloc(PyMethodObject *im) +method_dealloc(PyObject *self) { + PyMethodObject *im = _PyMethodObject_CAST(self); _PyObject_GC_UNTRACK(im); if (im->im_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *)im); @@ -274,8 +277,9 @@ method_richcompare(PyObject *self, PyObject *other, int op) } static PyObject * -method_repr(PyMethodObject *a) +method_repr(PyObject *op) { + PyMethodObject *a = _PyMethodObject_CAST(op); PyObject *self = a->im_self; PyObject *func = a->im_func; PyObject *funcname, *result; @@ -301,22 +305,26 @@ method_repr(PyMethodObject *a) } static Py_hash_t -method_hash(PyMethodObject *a) +method_hash(PyObject *self) { - Py_hash_t x, y; - x = PyObject_GenericHash(a->im_self); - y = PyObject_Hash(a->im_func); - if (y == -1) + PyMethodObject *a = _PyMethodObject_CAST(self); + Py_hash_t x = PyObject_GenericHash(a->im_self); + Py_hash_t y = PyObject_Hash(a->im_func); + if (y == -1) { return -1; + } + x = x ^ y; - if (x == -1) + if (x == -1) { x = -2; + } return x; } static int -method_traverse(PyMethodObject *im, visitproc visit, void *arg) +method_traverse(PyObject *self, visitproc visit, void *arg) { + PyMethodObject *im = _PyMethodObject_CAST(self); Py_VISIT(im->im_func); Py_VISIT(im->im_self); return 0; @@ -333,17 +341,17 @@ PyTypeObject PyMethod_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "method", .tp_basicsize = sizeof(PyMethodObject), - .tp_dealloc = (destructor)method_dealloc, + .tp_dealloc = method_dealloc, .tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall), - .tp_repr = (reprfunc)method_repr, - .tp_hash = (hashfunc)method_hash, + .tp_repr = method_repr, + .tp_hash = method_hash, .tp_call = PyVectorcall_Call, .tp_getattro = method_getattro, .tp_setattro = PyObject_GenericSetAttr, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_VECTORCALL, .tp_doc = method_new__doc__, - .tp_traverse = (traverseproc)method_traverse, + .tp_traverse = method_traverse, .tp_richcompare = method_richcompare, .tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist), .tp_methods = method_methods, @@ -399,7 +407,7 @@ instancemethod_get_doc(PyObject *self, void *context) } static PyGetSetDef instancemethod_getset[] = { - {"__doc__", (getter)instancemethod_get_doc, NULL, NULL}, + {"__doc__", instancemethod_get_doc, NULL, NULL}, {0} }; @@ -537,7 +545,7 @@ PyTypeObject PyInstanceMethod_Type = { .tp_name = "instancemethod", .tp_basicsize = sizeof(PyInstanceMethodObject), .tp_dealloc = instancemethod_dealloc, - .tp_repr = (reprfunc)instancemethod_repr, + .tp_repr = instancemethod_repr, .tp_call = instancemethod_call, .tp_getattro = instancemethod_getattro, .tp_setattro = PyObject_GenericSetAttr, diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 6f0b3f8b9a3262..8a2f4d32b911d9 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -2336,6 +2336,7 @@ _PyCode_ConstantKey(PyObject *op) if (op == Py_None || op == Py_Ellipsis || PyLong_CheckExact(op) || PyUnicode_CheckExact(op) + || PySlice_Check(op) /* code_richcompare() uses _PyCode_ConstantKey() internally */ || PyCode_Check(op)) { diff --git a/Objects/dictobject.c b/Objects/dictobject.c index ef9d23e62f95de..adfd91d1e4d63b 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -877,7 +877,7 @@ new_dict(PyInterpreterState *interp, mp->ma_keys = keys; mp->ma_values = values; mp->ma_used = used; - mp->ma_version_tag = DICT_NEXT_VERSION(interp); + mp->_ma_watcher_tag = 0; ASSERT_CONSISTENT(mp); return (PyObject *)mp; } @@ -1678,8 +1678,7 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp, } } - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_ADDED, mp, key, value); + _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value); mp->ma_keys->dk_version = 0; Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash); @@ -1698,7 +1697,6 @@ insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp, STORE_VALUE(ep, value); STORE_HASH(ep, hash); } - mp->ma_version_tag = new_version; STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1); STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1); assert(mp->ma_keys->dk_usable >= 0); @@ -1744,16 +1742,14 @@ insert_split_value(PyInterpreterState *interp, PyDictObject *mp, PyObject *key, MAINTAIN_TRACKING(mp, key, value); PyObject *old_value = mp->ma_values->values[ix]; if (old_value == NULL) { - uint64_t new_version = _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value); + _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value); STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value)); _PyDictValues_AddToInsertionOrder(mp->ma_values, ix); STORE_USED(mp, mp->ma_used + 1); - mp->ma_version_tag = new_version; } else { - uint64_t new_version = _PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value); + _PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value); STORE_SPLIT_VALUE(mp, ix, Py_NewRef(value)); - mp->ma_version_tag = new_version; // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault, // when dict only holds the strong reference to value in ep->me_value. Py_DECREF(old_value); @@ -1815,8 +1811,7 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp, } if (old_value != value) { - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_MODIFIED, mp, key, value); + _PyDict_NotifyEvent(interp, PyDict_EVENT_MODIFIED, mp, key, value); assert(old_value != NULL); assert(!_PyDict_HasSplitTable(mp)); if (DK_IS_UNICODE(mp->ma_keys)) { @@ -1827,7 +1822,6 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp, PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix]; STORE_VALUE(ep, value); } - mp->ma_version_tag = new_version; } Py_XDECREF(old_value); /* which **CAN** re-enter (see issue #22653) */ ASSERT_CONSISTENT(mp); @@ -1857,8 +1851,7 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp, Py_DECREF(value); return -1; } - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_ADDED, mp, key, value); + _PyDict_NotifyEvent(interp, PyDict_EVENT_ADDED, mp, key, value); /* We don't decref Py_EMPTY_KEYS here because it is immortal. */ assert(mp->ma_values == NULL); @@ -1879,7 +1872,6 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp, STORE_VALUE(ep, value); } STORE_USED(mp, mp->ma_used + 1); - mp->ma_version_tag = new_version; newkeys->dk_usable--; newkeys->dk_nentries++; // We store the keys last so no one can see them in a partially inconsistent @@ -2612,7 +2604,7 @@ delete_index_from_values(PyDictValues *values, Py_ssize_t ix) static void delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix, - PyObject *old_value, uint64_t new_version) + PyObject *old_value) { PyObject *old_key; @@ -2622,7 +2614,6 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix, assert(hashpos >= 0); STORE_USED(mp, mp->ma_used - 1); - mp->ma_version_tag = new_version; if (_PyDict_HasSplitTable(mp)) { assert(old_value == mp->ma_values->values[ix]); STORE_SPLIT_VALUE(mp, ix, NULL); @@ -2692,9 +2683,8 @@ delitem_knownhash_lock_held(PyObject *op, PyObject *key, Py_hash_t hash) } PyInterpreterState *interp = _PyInterpreterState_GET(); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_DELETED, mp, key, NULL); - delitem_common(mp, hash, ix, old_value, new_version); + _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL); + delitem_common(mp, hash, ix, old_value); return 0; } @@ -2740,9 +2730,8 @@ delitemif_lock_held(PyObject *op, PyObject *key, if (res > 0) { PyInterpreterState *interp = _PyInterpreterState_GET(); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_DELETED, mp, key, NULL); - delitem_common(mp, hash, ix, old_value, new_version); + _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL); + delitem_common(mp, hash, ix, old_value); return 1; } else { return 0; @@ -2786,11 +2775,9 @@ clear_lock_held(PyObject *op) } /* Empty the dict... */ PyInterpreterState *interp = _PyInterpreterState_GET(); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_CLEARED, mp, NULL, NULL); + _PyDict_NotifyEvent(interp, PyDict_EVENT_CLEARED, mp, NULL, NULL); // We don't inc ref empty keys because they're immortal ensure_shared_on_resize(mp); - mp->ma_version_tag = new_version; STORE_USED(mp, 0); if (oldvalues == NULL) { set_keys(mp, Py_EMPTY_KEYS); @@ -2950,9 +2937,8 @@ _PyDict_Pop_KnownHash(PyDictObject *mp, PyObject *key, Py_hash_t hash, assert(old_value != NULL); PyInterpreterState *interp = _PyInterpreterState_GET(); - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_DELETED, mp, key, NULL); - delitem_common(mp, hash, ix, Py_NewRef(old_value), new_version); + _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, mp, key, NULL); + delitem_common(mp, hash, ix, Py_NewRef(old_value)); ASSERT_CONSISTENT(mp); if (result) { @@ -3717,8 +3703,7 @@ dict_dict_merge(PyInterpreterState *interp, PyDictObject *mp, PyDictObject *othe (DK_LOG_SIZE(okeys) == PyDict_LOG_MINSIZE || USABLE_FRACTION(DK_SIZE(okeys)/2) < other->ma_used) ) { - uint64_t new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_CLONED, mp, (PyObject *)other, NULL); + _PyDict_NotifyEvent(interp, PyDict_EVENT_CLONED, mp, (PyObject *)other, NULL); PyDictKeysObject *keys = clone_combined_dict_keys(other); if (keys == NULL) return -1; @@ -3727,7 +3712,6 @@ dict_dict_merge(PyInterpreterState *interp, PyDictObject *mp, PyDictObject *othe dictkeys_decref(interp, mp->ma_keys, IS_DICT_SHARED(mp)); mp->ma_keys = keys; STORE_USED(mp, other->ma_used); - mp->ma_version_tag = new_version; ASSERT_CONSISTENT(mp); if (_PyObject_GC_IS_TRACKED(other) && !_PyObject_GC_IS_TRACKED(mp)) { @@ -3982,7 +3966,7 @@ copy_lock_held(PyObject *o) split_copy->ma_values = newvalues; split_copy->ma_keys = mp->ma_keys; split_copy->ma_used = mp->ma_used; - split_copy->ma_version_tag = DICT_NEXT_VERSION(interp); + split_copy->_ma_watcher_tag = 0; dictkeys_incref(mp->ma_keys); if (_PyObject_GC_IS_TRACKED(mp)) _PyObject_GC_TRACK(split_copy); @@ -4430,7 +4414,6 @@ dict_popitem_impl(PyDictObject *self) { Py_ssize_t i, j; PyObject *res; - uint64_t new_version; PyInterpreterState *interp = _PyInterpreterState_GET(); ASSERT_DICT_LOCKED(self); @@ -4473,8 +4456,7 @@ dict_popitem_impl(PyDictObject *self) assert(i >= 0); key = ep0[i].me_key; - new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_DELETED, self, key, NULL); + _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, self, key, NULL); hash = unicode_get_hash(key); value = ep0[i].me_value; ep0[i].me_key = NULL; @@ -4489,8 +4471,7 @@ dict_popitem_impl(PyDictObject *self) assert(i >= 0); key = ep0[i].me_key; - new_version = _PyDict_NotifyEvent( - interp, PyDict_EVENT_DELETED, self, key, NULL); + _PyDict_NotifyEvent(interp, PyDict_EVENT_DELETED, self, key, NULL); hash = ep0[i].me_hash; value = ep0[i].me_value; ep0[i].me_key = NULL; @@ -4508,7 +4489,6 @@ dict_popitem_impl(PyDictObject *self) /* We can't dk_usable++ since there is DKIX_DUMMY in indices */ STORE_KEYS_NENTRIES(self->ma_keys, i); STORE_USED(self, self->ma_used - 1); - self->ma_version_tag = new_version; ASSERT_CONSISTENT(self); return res; } @@ -4759,8 +4739,7 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyDictObject *d = (PyDictObject *)self; d->ma_used = 0; - d->ma_version_tag = DICT_NEXT_VERSION( - _PyInterpreterState_GET()); + d->_ma_watcher_tag = 0; dictkeys_incref(Py_EMPTY_KEYS); d->ma_keys = Py_EMPTY_KEYS; d->ma_values = NULL; @@ -7384,7 +7363,7 @@ PyDict_Watch(int watcher_id, PyObject* dict) if (validate_watcher_id(interp, watcher_id)) { return -1; } - ((PyDictObject*)dict)->ma_version_tag |= (1LL << watcher_id); + ((PyDictObject*)dict)->_ma_watcher_tag |= (1LL << watcher_id); return 0; } @@ -7399,7 +7378,7 @@ PyDict_Unwatch(int watcher_id, PyObject* dict) if (validate_watcher_id(interp, watcher_id)) { return -1; } - ((PyDictObject*)dict)->ma_version_tag &= ~(1LL << watcher_id); + ((PyDictObject*)dict)->_ma_watcher_tag &= ~(1LL << watcher_id); return 0; } diff --git a/Objects/exceptions.c b/Objects/exceptions.c index b3910855165494..c685481b13a93a 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2994,46 +2994,55 @@ UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * UnicodeEncodeError_str(PyObject *self) { - PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self; + PyUnicodeErrorObject *exc = (PyUnicodeErrorObject *)self; PyObject *result = NULL; PyObject *reason_str = NULL; PyObject *encoding_str = NULL; - if (!uself->object) + if (exc->object == NULL) { /* Not properly initialized. */ return PyUnicode_FromString(""); + } /* Get reason and encoding as strings, which they might not be if they've been modified after we were constructed. */ - reason_str = PyObject_Str(uself->reason); - if (reason_str == NULL) + reason_str = PyObject_Str(exc->reason); + if (reason_str == NULL) { goto done; - encoding_str = PyObject_Str(uself->encoding); - if (encoding_str == NULL) + } + encoding_str = PyObject_Str(exc->encoding); + if (encoding_str == NULL) { goto done; + } + + Py_ssize_t len = PyUnicode_GET_LENGTH(exc->object); + Py_ssize_t start = exc->start, end = exc->end; - if (uself->start < PyUnicode_GET_LENGTH(uself->object) && uself->end == uself->start+1) { - Py_UCS4 badchar = PyUnicode_ReadChar(uself->object, uself->start); + if ((start >= 0 && start < len) && (end >= 0 && end <= len) && end == start + 1) { + Py_UCS4 badchar = PyUnicode_ReadChar(exc->object, start); const char *fmt; - if (badchar <= 0xff) + if (badchar <= 0xff) { fmt = "'%U' codec can't encode character '\\x%02x' in position %zd: %U"; - else if (badchar <= 0xffff) + } + else if (badchar <= 0xffff) { fmt = "'%U' codec can't encode character '\\u%04x' in position %zd: %U"; - else + } + else { fmt = "'%U' codec can't encode character '\\U%08x' in position %zd: %U"; + } result = PyUnicode_FromFormat( fmt, encoding_str, (int)badchar, - uself->start, + start, reason_str); } else { result = PyUnicode_FromFormat( "'%U' codec can't encode characters in position %zd-%zd: %U", encoding_str, - uself->start, - uself->end-1, + start, + end - 1, reason_str); } done: @@ -3107,41 +3116,46 @@ UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * UnicodeDecodeError_str(PyObject *self) { - PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self; + PyUnicodeErrorObject *exc = (PyUnicodeErrorObject *)self; PyObject *result = NULL; PyObject *reason_str = NULL; PyObject *encoding_str = NULL; - if (!uself->object) + if (exc->object == NULL) { /* Not properly initialized. */ return PyUnicode_FromString(""); + } /* Get reason and encoding as strings, which they might not be if they've been modified after we were constructed. */ - reason_str = PyObject_Str(uself->reason); - if (reason_str == NULL) + reason_str = PyObject_Str(exc->reason); + if (reason_str == NULL) { goto done; - encoding_str = PyObject_Str(uself->encoding); - if (encoding_str == NULL) + } + encoding_str = PyObject_Str(exc->encoding); + if (encoding_str == NULL) { goto done; + } + + Py_ssize_t len = PyBytes_GET_SIZE(exc->object); + Py_ssize_t start = exc->start, end = exc->end; - if (uself->start < PyBytes_GET_SIZE(uself->object) && uself->end == uself->start+1) { - int byte = (int)(PyBytes_AS_STRING(((PyUnicodeErrorObject *)self)->object)[uself->start]&0xff); + if ((start >= 0 && start < len) && (end >= 0 && end <= len) && end == start + 1) { + int badbyte = (int)(PyBytes_AS_STRING(exc->object)[start] & 0xff); result = PyUnicode_FromFormat( "'%U' codec can't decode byte 0x%02x in position %zd: %U", encoding_str, - byte, - uself->start, + badbyte, + start, reason_str); } else { result = PyUnicode_FromFormat( "'%U' codec can't decode bytes in position %zd-%zd: %U", encoding_str, - uself->start, - uself->end-1, - reason_str - ); + start, + end - 1, + reason_str); } done: Py_XDECREF(reason_str); @@ -3204,42 +3218,49 @@ UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args, static PyObject * UnicodeTranslateError_str(PyObject *self) { - PyUnicodeErrorObject *uself = (PyUnicodeErrorObject *)self; + PyUnicodeErrorObject *exc = (PyUnicodeErrorObject *)self; PyObject *result = NULL; PyObject *reason_str = NULL; - if (!uself->object) + if (exc->object == NULL) { /* Not properly initialized. */ return PyUnicode_FromString(""); + } /* Get reason as a string, which it might not be if it's been modified after we were constructed. */ - reason_str = PyObject_Str(uself->reason); - if (reason_str == NULL) + reason_str = PyObject_Str(exc->reason); + if (reason_str == NULL) { goto done; + } + + Py_ssize_t len = PyUnicode_GET_LENGTH(exc->object); + Py_ssize_t start = exc->start, end = exc->end; - if (uself->start < PyUnicode_GET_LENGTH(uself->object) && uself->end == uself->start+1) { - Py_UCS4 badchar = PyUnicode_ReadChar(uself->object, uself->start); + if ((start >= 0 && start < len) && (end >= 0 && end <= len) && end == start + 1) { + Py_UCS4 badchar = PyUnicode_ReadChar(exc->object, start); const char *fmt; - if (badchar <= 0xff) + if (badchar <= 0xff) { fmt = "can't translate character '\\x%02x' in position %zd: %U"; - else if (badchar <= 0xffff) + } + else if (badchar <= 0xffff) { fmt = "can't translate character '\\u%04x' in position %zd: %U"; - else + } + else { fmt = "can't translate character '\\U%08x' in position %zd: %U"; + } result = PyUnicode_FromFormat( fmt, (int)badchar, - uself->start, - reason_str - ); - } else { + start, + reason_str); + } + else { result = PyUnicode_FromFormat( "can't translate characters in position %zd-%zd: %U", - uself->start, - uself->end-1, - reason_str - ); + start, + end - 1, + reason_str); } done: Py_XDECREF(reason_str); diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 8df0da800980a9..855d1a2eeca819 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -128,7 +128,7 @@ _PyFunction_FromConstructor(PyFrameConstructor *constr) op->func_annotate = NULL; op->func_typeparams = NULL; op->vectorcall = _PyFunction_Vectorcall; - op->func_version = 0; + op->func_version = FUNC_VERSION_UNSET; // NOTE: functions created via FrameConstructor do not use deferred // reference counting because they are typically not part of cycles // nor accessed by multiple threads. @@ -207,7 +207,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname op->func_annotate = NULL; op->func_typeparams = NULL; op->vectorcall = _PyFunction_Vectorcall; - op->func_version = 0; + op->func_version = FUNC_VERSION_UNSET; if ((code_obj->co_flags & CO_NESTED) == 0) { // Use deferred reference counting for top-level functions, but not // nested functions because they are more likely to capture variables, @@ -287,31 +287,59 @@ functions is running. */ +static inline struct _func_version_cache_item * +get_cache_item(PyInterpreterState *interp, uint32_t version) +{ + return interp->func_state.func_version_cache + + (version % FUNC_VERSION_CACHE_SIZE); +} + void _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version) { + assert(func->func_version == FUNC_VERSION_UNSET); + assert(version >= FUNC_VERSION_FIRST_VALID); + // This should only be called from MAKE_FUNCTION. No code is specialized + // based on the version, so we do not need to stop the world to set it. + func->func_version = version; #ifndef Py_GIL_DISABLED PyInterpreterState *interp = _PyInterpreterState_GET(); - if (func->func_version != 0) { - struct _func_version_cache_item *slot = - interp->func_state.func_version_cache - + (func->func_version % FUNC_VERSION_CACHE_SIZE); - if (slot->func == func) { - slot->func = NULL; - // Leave slot->code alone, there may be use for it. - } - } + struct _func_version_cache_item *slot = get_cache_item(interp, version); + slot->func = func; + slot->code = func->func_code; #endif - func->func_version = version; +} + +static void +func_clear_version(PyInterpreterState *interp, PyFunctionObject *func) +{ + if (func->func_version < FUNC_VERSION_FIRST_VALID) { + // Version was never set or has already been cleared. + return; + } #ifndef Py_GIL_DISABLED - if (version != 0) { - struct _func_version_cache_item *slot = - interp->func_state.func_version_cache - + (version % FUNC_VERSION_CACHE_SIZE); - slot->func = func; - slot->code = func->func_code; + struct _func_version_cache_item *slot = + get_cache_item(interp, func->func_version); + if (slot->func == func) { + slot->func = NULL; + // Leave slot->code alone, there may be use for it. } #endif + func->func_version = FUNC_VERSION_CLEARED; +} + +// Called when any of the critical function attributes are changed +static void +_PyFunction_ClearVersion(PyFunctionObject *func) +{ + if (func->func_version < FUNC_VERSION_FIRST_VALID) { + // Version was never set or has already been cleared. + return; + } + PyInterpreterState *interp = _PyInterpreterState_GET(); + _PyEval_StopTheWorld(interp); + func_clear_version(interp, func); + _PyEval_StartTheWorld(interp); } void @@ -319,9 +347,7 @@ _PyFunction_ClearCodeByVersion(uint32_t version) { #ifndef Py_GIL_DISABLED PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _func_version_cache_item *slot = - interp->func_state.func_version_cache - + (version % FUNC_VERSION_CACHE_SIZE); + struct _func_version_cache_item *slot = get_cache_item(interp, version); if (slot->code) { assert(PyCode_Check(slot->code)); PyCodeObject *code = (PyCodeObject *)slot->code; @@ -340,9 +366,7 @@ _PyFunction_LookupByVersion(uint32_t version, PyObject **p_code) return NULL; #else PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _func_version_cache_item *slot = - interp->func_state.func_version_cache - + (version % FUNC_VERSION_CACHE_SIZE); + struct _func_version_cache_item *slot = get_cache_item(interp, version); if (slot->code) { assert(PyCode_Check(slot->code)); PyCodeObject *code = (PyCodeObject *)slot->code; @@ -431,7 +455,7 @@ PyFunction_SetDefaults(PyObject *op, PyObject *defaults) } handle_func_event(PyFunction_EVENT_MODIFY_DEFAULTS, (PyFunctionObject *) op, defaults); - _PyFunction_SetVersion((PyFunctionObject *)op, 0); + _PyFunction_ClearVersion((PyFunctionObject *)op); Py_XSETREF(((PyFunctionObject *)op)->func_defaults, defaults); return 0; } @@ -440,7 +464,7 @@ void PyFunction_SetVectorcall(PyFunctionObject *func, vectorcallfunc vectorcall) { assert(func != NULL); - _PyFunction_SetVersion(func, 0); + _PyFunction_ClearVersion(func); func->vectorcall = vectorcall; } @@ -473,7 +497,7 @@ PyFunction_SetKwDefaults(PyObject *op, PyObject *defaults) } handle_func_event(PyFunction_EVENT_MODIFY_KWDEFAULTS, (PyFunctionObject *) op, defaults); - _PyFunction_SetVersion((PyFunctionObject *)op, 0); + _PyFunction_ClearVersion((PyFunctionObject *)op); Py_XSETREF(((PyFunctionObject *)op)->func_kwdefaults, defaults); return 0; } @@ -506,7 +530,7 @@ PyFunction_SetClosure(PyObject *op, PyObject *closure) Py_TYPE(closure)->tp_name); return -1; } - _PyFunction_SetVersion((PyFunctionObject *)op, 0); + _PyFunction_ClearVersion((PyFunctionObject *)op); Py_XSETREF(((PyFunctionObject *)op)->func_closure, closure); return 0; } @@ -604,8 +628,9 @@ static PyMemberDef func_memberlist[] = { }; static PyObject * -func_get_code(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_code(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (PySys_Audit("object.__getattr__", "Os", op, "__code__") < 0) { return NULL; } @@ -614,10 +639,9 @@ func_get_code(PyFunctionObject *op, void *Py_UNUSED(ignored)) } static int -func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_code(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { - Py_ssize_t nclosure; - int nfree; + PyFunctionObject *op = _PyFunction_CAST(self); /* Not legal to del f.func_code or to set it to anything * other than a code object. */ @@ -632,9 +656,9 @@ func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) return -1; } - nfree = ((PyCodeObject *)value)->co_nfreevars; - nclosure = (op->func_closure == NULL ? 0 : - PyTuple_GET_SIZE(op->func_closure)); + int nfree = ((PyCodeObject *)value)->co_nfreevars; + Py_ssize_t nclosure = (op->func_closure == NULL ? 0 : + PyTuple_GET_SIZE(op->func_closure)); if (nclosure != nfree) { PyErr_Format(PyExc_ValueError, "%U() requires a code object with %zd free vars," @@ -658,20 +682,22 @@ func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) } handle_func_event(PyFunction_EVENT_MODIFY_CODE, op, value); - _PyFunction_SetVersion(op, 0); + _PyFunction_ClearVersion(op); Py_XSETREF(op->func_code, Py_NewRef(value)); return 0; } static PyObject * -func_get_name(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_name(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); return Py_NewRef(op->func_name); } static int -func_set_name(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_name(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); /* Not legal to del f.func_name or to set it to anything * other than a string object. */ if (value == NULL || !PyUnicode_Check(value)) { @@ -684,14 +710,16 @@ func_set_name(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) } static PyObject * -func_get_qualname(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_qualname(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); return Py_NewRef(op->func_qualname); } static int -func_set_qualname(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_qualname(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); /* Not legal to del f.__qualname__ or to set it to anything * other than a string object. */ if (value == NULL || !PyUnicode_Check(value)) { @@ -704,8 +732,9 @@ func_set_qualname(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored } static PyObject * -func_get_defaults(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_defaults(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (PySys_Audit("object.__getattr__", "Os", op, "__defaults__") < 0) { return NULL; } @@ -716,10 +745,11 @@ func_get_defaults(PyFunctionObject *op, void *Py_UNUSED(ignored)) } static int -func_set_defaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_defaults(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { /* Legal to del f.func_defaults. * Can only set func_defaults to NULL or a tuple. */ + PyFunctionObject *op = _PyFunction_CAST(self); if (value == Py_None) value = NULL; if (value != NULL && !PyTuple_Check(value)) { @@ -738,14 +768,15 @@ func_set_defaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored } handle_func_event(PyFunction_EVENT_MODIFY_DEFAULTS, op, value); - _PyFunction_SetVersion(op, 0); + _PyFunction_ClearVersion(op); Py_XSETREF(op->func_defaults, Py_XNewRef(value)); return 0; } static PyObject * -func_get_kwdefaults(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_kwdefaults(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (PySys_Audit("object.__getattr__", "Os", op, "__kwdefaults__") < 0) { return NULL; @@ -757,8 +788,9 @@ func_get_kwdefaults(PyFunctionObject *op, void *Py_UNUSED(ignored)) } static int -func_set_kwdefaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_kwdefaults(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (value == Py_None) value = NULL; /* Legal to del f.func_kwdefaults. @@ -779,14 +811,15 @@ func_set_kwdefaults(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignor } handle_func_event(PyFunction_EVENT_MODIFY_KWDEFAULTS, op, value); - _PyFunction_SetVersion(op, 0); + _PyFunction_ClearVersion(op); Py_XSETREF(op->func_kwdefaults, Py_XNewRef(value)); return 0; } static PyObject * -func_get_annotate(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_annotate(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (op->func_annotate == NULL) { Py_RETURN_NONE; } @@ -794,8 +827,9 @@ func_get_annotate(PyFunctionObject *op, void *Py_UNUSED(ignored)) } static int -func_set_annotate(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_annotate(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (value == NULL) { PyErr_SetString(PyExc_TypeError, "__annotate__ cannot be deleted"); @@ -818,8 +852,9 @@ func_set_annotate(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored } static PyObject * -func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_annotations(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (op->func_annotations == NULL && (op->func_annotate == NULL || !PyCallable_Check(op->func_annotate))) { op->func_annotations = PyDict_New(); @@ -831,8 +866,9 @@ func_get_annotations(PyFunctionObject *op, void *Py_UNUSED(ignored)) } static int -func_set_annotations(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_annotations(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (value == Py_None) value = NULL; /* Legal to del f.func_annotations. @@ -849,8 +885,9 @@ func_set_annotations(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(igno } static PyObject * -func_get_type_params(PyFunctionObject *op, void *Py_UNUSED(ignored)) +func_get_type_params(PyObject *self, void *Py_UNUSED(ignored)) { + PyFunctionObject *op = _PyFunction_CAST(self); if (op->func_typeparams == NULL) { return PyTuple_New(0); } @@ -860,10 +897,11 @@ func_get_type_params(PyFunctionObject *op, void *Py_UNUSED(ignored)) } static int -func_set_type_params(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored)) +func_set_type_params(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { /* Not legal to del f.__type_params__ or to set it to anything * other than a tuple object. */ + PyFunctionObject *op = _PyFunction_CAST(self); if (value == NULL || !PyTuple_Check(value)) { PyErr_SetString(PyExc_TypeError, "__type_params__ must be set to a tuple"); @@ -885,19 +923,15 @@ _Py_set_function_type_params(PyThreadState *Py_UNUSED(ignored), PyObject *func, } static PyGetSetDef func_getsetlist[] = { - {"__code__", (getter)func_get_code, (setter)func_set_code}, - {"__defaults__", (getter)func_get_defaults, - (setter)func_set_defaults}, - {"__kwdefaults__", (getter)func_get_kwdefaults, - (setter)func_set_kwdefaults}, - {"__annotations__", (getter)func_get_annotations, - (setter)func_set_annotations}, - {"__annotate__", (getter)func_get_annotate, (setter)func_set_annotate}, + {"__code__", func_get_code, func_set_code}, + {"__defaults__", func_get_defaults, func_set_defaults}, + {"__kwdefaults__", func_get_kwdefaults, func_set_kwdefaults}, + {"__annotations__", func_get_annotations, func_set_annotations}, + {"__annotate__", func_get_annotate, func_set_annotate}, {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict}, - {"__name__", (getter)func_get_name, (setter)func_set_name}, - {"__qualname__", (getter)func_get_qualname, (setter)func_set_qualname}, - {"__type_params__", (getter)func_get_type_params, - (setter)func_set_type_params}, + {"__name__", func_get_name, func_set_name}, + {"__qualname__", func_get_qualname, func_set_qualname}, + {"__type_params__", func_get_type_params, func_set_type_params}, {NULL} /* Sentinel */ }; @@ -1017,9 +1051,10 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, } static int -func_clear(PyFunctionObject *op) +func_clear(PyObject *self) { - _PyFunction_SetVersion(op, 0); + PyFunctionObject *op = _PyFunction_CAST(self); + func_clear_version(_PyInterpreterState_GET(), op); Py_CLEAR(op->func_globals); Py_CLEAR(op->func_builtins); Py_CLEAR(op->func_module); @@ -1042,8 +1077,9 @@ func_clear(PyFunctionObject *op) } static void -func_dealloc(PyFunctionObject *op) +func_dealloc(PyObject *self) { + PyFunctionObject *op = _PyFunction_CAST(self); assert(Py_REFCNT(op) == 0); Py_SET_REFCNT(op, 1); handle_func_event(PyFunction_EVENT_DESTROY, op, NULL); @@ -1056,8 +1092,7 @@ func_dealloc(PyFunctionObject *op) if (op->func_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) op); } - _PyFunction_SetVersion(op, 0); - (void)func_clear(op); + (void)func_clear((PyObject*)op); // These aren't cleared by func_clear(). Py_DECREF(op->func_code); Py_DECREF(op->func_name); @@ -1066,15 +1101,17 @@ func_dealloc(PyFunctionObject *op) } static PyObject* -func_repr(PyFunctionObject *op) +func_repr(PyObject *self) { + PyFunctionObject *op = _PyFunction_CAST(self); return PyUnicode_FromFormat("", op->func_qualname, op); } static int -func_traverse(PyFunctionObject *f, visitproc visit, void *arg) +func_traverse(PyObject *self, visitproc visit, void *arg) { + PyFunctionObject *f = _PyFunction_CAST(self); Py_VISIT(f->func_code); Py_VISIT(f->func_globals); Py_VISIT(f->func_builtins); @@ -1107,12 +1144,12 @@ PyTypeObject PyFunction_Type = { "function", sizeof(PyFunctionObject), 0, - (destructor)func_dealloc, /* tp_dealloc */ + func_dealloc, /* tp_dealloc */ offsetof(PyFunctionObject, vectorcall), /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)func_repr, /* tp_repr */ + func_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -1126,8 +1163,8 @@ PyTypeObject PyFunction_Type = { Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_METHOD_DESCRIPTOR, /* tp_flags */ func_new__doc__, /* tp_doc */ - (traverseproc)func_traverse, /* tp_traverse */ - (inquiry)func_clear, /* tp_clear */ + func_traverse, /* tp_traverse */ + func_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ @@ -1251,9 +1288,14 @@ typedef struct { PyObject *cm_dict; } classmethod; +#define _PyClassMethod_CAST(cm) \ + (assert(PyObject_TypeCheck((cm), &PyClassMethod_Type)), \ + _Py_CAST(classmethod*, cm)) + static void -cm_dealloc(classmethod *cm) +cm_dealloc(PyObject *self) { + classmethod *cm = _PyClassMethod_CAST(self); _PyObject_GC_UNTRACK((PyObject *)cm); Py_XDECREF(cm->cm_callable); Py_XDECREF(cm->cm_dict); @@ -1261,16 +1303,18 @@ cm_dealloc(classmethod *cm) } static int -cm_traverse(classmethod *cm, visitproc visit, void *arg) +cm_traverse(PyObject *self, visitproc visit, void *arg) { + classmethod *cm = _PyClassMethod_CAST(self); Py_VISIT(cm->cm_callable); Py_VISIT(cm->cm_dict); return 0; } static int -cm_clear(classmethod *cm) +cm_clear(PyObject *self) { + classmethod *cm = _PyClassMethod_CAST(self); Py_CLEAR(cm->cm_callable); Py_CLEAR(cm->cm_dict); return 0; @@ -1317,8 +1361,9 @@ static PyMemberDef cm_memberlist[] = { }; static PyObject * -cm_get___isabstractmethod__(classmethod *cm, void *closure) +cm_get___isabstractmethod__(PyObject *self, void *closure) { + classmethod *cm = _PyClassMethod_CAST(self); int res = _PyObject_IsAbstract(cm->cm_callable); if (res == -1) { return NULL; @@ -1330,42 +1375,46 @@ cm_get___isabstractmethod__(classmethod *cm, void *closure) } static PyObject * -cm_get___annotations__(classmethod *cm, void *closure) +cm_get___annotations__(PyObject *self, void *closure) { + classmethod *cm = _PyClassMethod_CAST(self); return descriptor_get_wrapped_attribute(cm->cm_callable, cm->cm_dict, &_Py_ID(__annotations__)); } static int -cm_set___annotations__(classmethod *cm, PyObject *value, void *closure) +cm_set___annotations__(PyObject *self, PyObject *value, void *closure) { + classmethod *cm = _PyClassMethod_CAST(self); return descriptor_set_wrapped_attribute(cm->cm_dict, &_Py_ID(__annotations__), value, "classmethod"); } static PyObject * -cm_get___annotate__(classmethod *cm, void *closure) +cm_get___annotate__(PyObject *self, void *closure) { + classmethod *cm = _PyClassMethod_CAST(self); return descriptor_get_wrapped_attribute(cm->cm_callable, cm->cm_dict, &_Py_ID(__annotate__)); } static int -cm_set___annotate__(classmethod *cm, PyObject *value, void *closure) +cm_set___annotate__(PyObject *self, PyObject *value, void *closure) { + classmethod *cm = _PyClassMethod_CAST(self); return descriptor_set_wrapped_attribute(cm->cm_dict, &_Py_ID(__annotate__), value, "classmethod"); } static PyGetSetDef cm_getsetlist[] = { - {"__isabstractmethod__", - (getter)cm_get___isabstractmethod__, NULL, NULL, NULL}, + {"__isabstractmethod__", cm_get___isabstractmethod__, NULL, NULL, NULL}, {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL}, - {"__annotations__", (getter)cm_get___annotations__, (setter)cm_set___annotations__, NULL, NULL}, - {"__annotate__", (getter)cm_get___annotate__, (setter)cm_set___annotate__, NULL, NULL}, + {"__annotations__", cm_get___annotations__, cm_set___annotations__, NULL, NULL}, + {"__annotate__", cm_get___annotate__, cm_set___annotate__, NULL, NULL}, {NULL} /* Sentinel */ }; static PyObject* -cm_repr(classmethod *cm) +cm_repr(PyObject *self) { + classmethod *cm = _PyClassMethod_CAST(self); return PyUnicode_FromFormat("", cm->cm_callable); } @@ -1397,12 +1446,12 @@ PyTypeObject PyClassMethod_Type = { "classmethod", sizeof(classmethod), 0, - (destructor)cm_dealloc, /* tp_dealloc */ + cm_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)cm_repr, /* tp_repr */ + cm_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -1414,14 +1463,14 @@ PyTypeObject PyClassMethod_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, classmethod_doc, /* tp_doc */ - (traverseproc)cm_traverse, /* tp_traverse */ - (inquiry)cm_clear, /* tp_clear */ + cm_traverse, /* tp_traverse */ + cm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - cm_memberlist, /* tp_members */ + cm_memberlist, /* tp_members */ cm_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ @@ -1470,9 +1519,14 @@ typedef struct { PyObject *sm_dict; } staticmethod; +#define _PyStaticMethod_CAST(cm) \ + (assert(PyObject_TypeCheck((cm), &PyStaticMethod_Type)), \ + _Py_CAST(staticmethod*, cm)) + static void -sm_dealloc(staticmethod *sm) +sm_dealloc(PyObject *self) { + staticmethod *sm = _PyStaticMethod_CAST(self); _PyObject_GC_UNTRACK((PyObject *)sm); Py_XDECREF(sm->sm_callable); Py_XDECREF(sm->sm_dict); @@ -1480,16 +1534,18 @@ sm_dealloc(staticmethod *sm) } static int -sm_traverse(staticmethod *sm, visitproc visit, void *arg) +sm_traverse(PyObject *self, visitproc visit, void *arg) { + staticmethod *sm = _PyStaticMethod_CAST(self); Py_VISIT(sm->sm_callable); Py_VISIT(sm->sm_dict); return 0; } static int -sm_clear(staticmethod *sm) +sm_clear(PyObject *self) { + staticmethod *sm = _PyStaticMethod_CAST(self); Py_CLEAR(sm->sm_callable); Py_CLEAR(sm->sm_dict); return 0; @@ -1540,8 +1596,9 @@ static PyMemberDef sm_memberlist[] = { }; static PyObject * -sm_get___isabstractmethod__(staticmethod *sm, void *closure) +sm_get___isabstractmethod__(PyObject *self, void *closure) { + staticmethod *sm = _PyStaticMethod_CAST(self); int res = _PyObject_IsAbstract(sm->sm_callable); if (res == -1) { return NULL; @@ -1553,41 +1610,45 @@ sm_get___isabstractmethod__(staticmethod *sm, void *closure) } static PyObject * -sm_get___annotations__(staticmethod *sm, void *closure) +sm_get___annotations__(PyObject *self, void *closure) { + staticmethod *sm = _PyStaticMethod_CAST(self); return descriptor_get_wrapped_attribute(sm->sm_callable, sm->sm_dict, &_Py_ID(__annotations__)); } static int -sm_set___annotations__(staticmethod *sm, PyObject *value, void *closure) +sm_set___annotations__(PyObject *self, PyObject *value, void *closure) { + staticmethod *sm = _PyStaticMethod_CAST(self); return descriptor_set_wrapped_attribute(sm->sm_dict, &_Py_ID(__annotations__), value, "staticmethod"); } static PyObject * -sm_get___annotate__(staticmethod *sm, void *closure) +sm_get___annotate__(PyObject *self, void *closure) { + staticmethod *sm = _PyStaticMethod_CAST(self); return descriptor_get_wrapped_attribute(sm->sm_callable, sm->sm_dict, &_Py_ID(__annotate__)); } static int -sm_set___annotate__(staticmethod *sm, PyObject *value, void *closure) +sm_set___annotate__(PyObject *self, PyObject *value, void *closure) { + staticmethod *sm = _PyStaticMethod_CAST(self); return descriptor_set_wrapped_attribute(sm->sm_dict, &_Py_ID(__annotate__), value, "staticmethod"); } static PyGetSetDef sm_getsetlist[] = { - {"__isabstractmethod__", - (getter)sm_get___isabstractmethod__, NULL, NULL, NULL}, + {"__isabstractmethod__", sm_get___isabstractmethod__, NULL, NULL, NULL}, {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, NULL, NULL}, - {"__annotations__", (getter)sm_get___annotations__, (setter)sm_set___annotations__, NULL, NULL}, - {"__annotate__", (getter)sm_get___annotate__, (setter)sm_set___annotate__, NULL, NULL}, + {"__annotations__", sm_get___annotations__, sm_set___annotations__, NULL, NULL}, + {"__annotate__", sm_get___annotate__, sm_set___annotate__, NULL, NULL}, {NULL} /* Sentinel */ }; static PyObject* -sm_repr(staticmethod *sm) +sm_repr(PyObject *self) { + staticmethod *sm = _PyStaticMethod_CAST(self); return PyUnicode_FromFormat("", sm->sm_callable); } @@ -1617,12 +1678,12 @@ PyTypeObject PyStaticMethod_Type = { "staticmethod", sizeof(staticmethod), 0, - (destructor)sm_dealloc, /* tp_dealloc */ + sm_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)sm_repr, /* tp_repr */ + sm_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -1634,14 +1695,14 @@ PyTypeObject PyStaticMethod_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, staticmethod_doc, /* tp_doc */ - (traverseproc)sm_traverse, /* tp_traverse */ - (inquiry)sm_clear, /* tp_clear */ + sm_traverse, /* tp_traverse */ + sm_clear, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ - sm_memberlist, /* tp_members */ + sm_memberlist, /* tp_members */ sm_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ diff --git a/Objects/genobject.c b/Objects/genobject.c index 41cf8fdcc9dee8..19c2c4e3331a89 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -17,9 +17,20 @@ #include "pystats.h" -static PyObject *gen_close(PyGenObject *, PyObject *); -static PyObject *async_gen_asend_new(PyAsyncGenObject *, PyObject *); -static PyObject *async_gen_athrow_new(PyAsyncGenObject *, PyObject *); +// Forward declarations +static PyObject* gen_close(PyObject *, PyObject *); +static PyObject* async_gen_asend_new(PyAsyncGenObject *, PyObject *); +static PyObject* async_gen_athrow_new(PyAsyncGenObject *, PyObject *); + + +#define _PyGen_CAST(op) \ + _Py_CAST(PyGenObject*, (op)) +#define _PyCoroObject_CAST(op) \ + (assert(PyCoro_CheckExact(op)), \ + _Py_CAST(PyCoroObject*, (op))) +#define _PyAsyncGenObject_CAST(op) \ + _Py_CAST(PyAsyncGenObject*, (op)) + static const char *NON_INIT_CORO_MSG = "can't send non-None value to a " "just-started coroutine"; @@ -42,8 +53,9 @@ PyGen_GetCode(PyGenObject *gen) { } static int -gen_traverse(PyGenObject *gen, visitproc visit, void *arg) +gen_traverse(PyObject *self, visitproc visit, void *arg) { + PyGenObject *gen = _PyGen_CAST(self); Py_VISIT(gen->gi_name); Py_VISIT(gen->gi_qualname); if (gen->gi_frame_state != FRAME_CLEARED) { @@ -107,7 +119,7 @@ _PyGen_Finalize(PyObject *self) _PyErr_WarnUnawaitedCoroutine((PyObject *)gen); } else { - PyObject *res = gen_close(gen, NULL); + PyObject *res = gen_close((PyObject*)gen, NULL); if (res == NULL) { if (PyErr_Occurred()) { PyErr_WriteUnraisable(self); @@ -123,9 +135,9 @@ _PyGen_Finalize(PyObject *self) } static void -gen_dealloc(PyGenObject *gen) +gen_dealloc(PyObject *self) { - PyObject *self = (PyObject *) gen; + PyGenObject *gen = _PyGen_CAST(self); _PyObject_GC_UNTRACK(gen); @@ -262,8 +274,9 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, } static PySendResult -PyGen_am_send(PyGenObject *gen, PyObject *arg, PyObject **result) +PyGen_am_send(PyObject *self, PyObject *arg, PyObject **result) { + PyGenObject *gen = _PyGen_CAST(self); return gen_send_ex2(gen, arg, result, 0, 0); } @@ -292,9 +305,9 @@ PyDoc_STRVAR(send_doc, return next yielded value or raise StopIteration."); static PyObject * -gen_send(PyGenObject *gen, PyObject *arg) +gen_send(PyObject *gen, PyObject *arg) { - return gen_send_ex(gen, arg, 0, 0); + return gen_send_ex((PyGenObject*)gen, arg, 0, 0); } PyDoc_STRVAR(close_doc, @@ -311,7 +324,7 @@ gen_close_iter(PyObject *yf) PyObject *retval = NULL; if (PyGen_CheckExact(yf) || PyCoro_CheckExact(yf)) { - retval = gen_close((PyGenObject *)yf, NULL); + retval = gen_close((PyObject *)yf, NULL); if (retval == NULL) return -1; } @@ -356,11 +369,9 @@ _PyGen_yf(PyGenObject *gen) } static PyObject * -gen_close(PyGenObject *gen, PyObject *args) +gen_close(PyObject *self, PyObject *args) { - PyObject *retval; - int err = 0; - + PyGenObject *gen = _PyGen_CAST(self); if (gen->gi_frame_state == FRAME_CREATED) { gen->gi_frame_state = FRAME_COMPLETED; @@ -369,7 +380,9 @@ gen_close(PyGenObject *gen, PyObject *args) if (FRAME_STATE_FINISHED(gen->gi_frame_state)) { Py_RETURN_NONE; } + PyObject *yf = _PyGen_yf(gen); + int err = 0; if (yf) { PyFrameState state = gen->gi_frame_state; gen->gi_frame_state = FRAME_EXECUTING; @@ -394,7 +407,8 @@ gen_close(PyGenObject *gen, PyObject *args) if (err == 0) { PyErr_SetNone(PyExc_GeneratorExit); } - retval = gen_send_ex(gen, Py_None, 1, 1); + + PyObject *retval = gen_send_ex(gen, Py_None, 1, 1); if (retval) { const char *msg = "generator ignored GeneratorExit"; if (PyCoro_CheckExact(gen)) { @@ -407,10 +421,12 @@ gen_close(PyGenObject *gen, PyObject *args) return NULL; } assert(PyErr_Occurred()); + if (PyErr_ExceptionMatches(PyExc_GeneratorExit)) { PyErr_Clear(); /* ignore this error */ Py_RETURN_NONE; } + /* if the generator returned a value while closing, StopIteration was * raised in gen_send_ex() above; retrieve and return the value here */ if (_PyGen_FetchStopIterationValue(&retval) == 0) { @@ -587,10 +603,12 @@ gen_throw(PyGenObject *gen, PyObject *const *args, Py_ssize_t nargs) static PyObject * -gen_iternext(PyGenObject *gen) +gen_iternext(PyObject *self) { + assert(PyGen_CheckExact(self) || PyCoro_CheckExact(self)); + PyGenObject *gen = _PyGen_CAST(self); + PyObject *result; - assert(PyGen_CheckExact(gen) || PyCoro_CheckExact(gen)); if (gen_send_ex2(gen, NULL, &result, 0, 0) == PYGEN_RETURN) { if (result != Py_None) { _PyGen_SetStopIterationValue(result); @@ -664,21 +682,24 @@ _PyGen_FetchStopIterationValue(PyObject **pvalue) } static PyObject * -gen_repr(PyGenObject *gen) +gen_repr(PyObject *self) { + PyGenObject *gen = _PyGen_CAST(self); return PyUnicode_FromFormat("", gen->gi_qualname, gen); } static PyObject * -gen_get_name(PyGenObject *op, void *Py_UNUSED(ignored)) +gen_get_name(PyObject *self, void *Py_UNUSED(ignored)) { + PyGenObject *op = _PyGen_CAST(self); return Py_NewRef(op->gi_name); } static int -gen_set_name(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored)) +gen_set_name(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyGenObject *op = _PyGen_CAST(self); /* Not legal to del gen.gi_name or to set it to anything * other than a string object. */ if (value == NULL || !PyUnicode_Check(value)) { @@ -691,14 +712,16 @@ gen_set_name(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored)) } static PyObject * -gen_get_qualname(PyGenObject *op, void *Py_UNUSED(ignored)) +gen_get_qualname(PyObject *self, void *Py_UNUSED(ignored)) { + PyGenObject *op = _PyGen_CAST(self); return Py_NewRef(op->gi_qualname); } static int -gen_set_qualname(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored)) +gen_set_qualname(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyGenObject *op = _PyGen_CAST(self); /* Not legal to del gen.__qualname__ or to set it to anything * other than a string object. */ if (value == NULL || !PyUnicode_Check(value)) { @@ -711,18 +734,20 @@ gen_set_qualname(PyGenObject *op, PyObject *value, void *Py_UNUSED(ignored)) } static PyObject * -gen_getyieldfrom(PyGenObject *gen, void *Py_UNUSED(ignored)) +gen_getyieldfrom(PyObject *gen, void *Py_UNUSED(ignored)) { - PyObject *yf = _PyGen_yf(gen); - if (yf == NULL) + PyObject *yf = _PyGen_yf(_PyGen_CAST(gen)); + if (yf == NULL) { Py_RETURN_NONE; + } return yf; } static PyObject * -gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored)) +gen_getrunning(PyObject *self, void *Py_UNUSED(ignored)) { + PyGenObject *gen = _PyGen_CAST(self); if (gen->gi_frame_state == FRAME_EXECUTING) { Py_RETURN_TRUE; } @@ -730,8 +755,9 @@ gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored)) } static PyObject * -gen_getsuspended(PyGenObject *gen, void *Py_UNUSED(ignored)) +gen_getsuspended(PyObject *self, void *Py_UNUSED(ignored)) { + PyGenObject *gen = _PyGen_CAST(self); return PyBool_FromLong(FRAME_STATE_SUSPENDED(gen->gi_frame_state)); } @@ -748,8 +774,9 @@ _gen_getframe(PyGenObject *gen, const char *const name) } static PyObject * -gen_getframe(PyGenObject *gen, void *Py_UNUSED(ignored)) +gen_getframe(PyObject *self, void *Py_UNUSED(ignored)) { + PyGenObject *gen = _PyGen_CAST(self); return _gen_getframe(gen, "gi_frame"); } @@ -763,22 +790,23 @@ _gen_getcode(PyGenObject *gen, const char *const name) } static PyObject * -gen_getcode(PyGenObject *gen, void *Py_UNUSED(ignored)) +gen_getcode(PyObject *self, void *Py_UNUSED(ignored)) { + PyGenObject *gen = _PyGen_CAST(self); return _gen_getcode(gen, "gi_code"); } static PyGetSetDef gen_getsetlist[] = { - {"__name__", (getter)gen_get_name, (setter)gen_set_name, + {"__name__", gen_get_name, gen_set_name, PyDoc_STR("name of the generator")}, - {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, + {"__qualname__", gen_get_qualname, gen_set_qualname, PyDoc_STR("qualified name of the generator")}, - {"gi_yieldfrom", (getter)gen_getyieldfrom, NULL, + {"gi_yieldfrom", gen_getyieldfrom, NULL, PyDoc_STR("object being iterated by yield from, or None")}, - {"gi_running", (getter)gen_getrunning, NULL, NULL}, - {"gi_frame", (getter)gen_getframe, NULL, NULL}, - {"gi_suspended", (getter)gen_getsuspended, NULL, NULL}, - {"gi_code", (getter)gen_getcode, NULL, NULL}, + {"gi_running", gen_getrunning, NULL, NULL}, + {"gi_frame", gen_getframe, NULL, NULL}, + {"gi_suspended", gen_getsuspended, NULL, NULL}, + {"gi_code", gen_getcode, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -800,9 +828,9 @@ PyDoc_STRVAR(sizeof__doc__, "gen.__sizeof__() -> size of gen in memory, in bytes"); static PyMethodDef gen_methods[] = { - {"send",(PyCFunction)gen_send, METH_O, send_doc}, - {"throw",_PyCFunction_CAST(gen_throw), METH_FASTCALL, throw_doc}, - {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc}, + {"send", gen_send, METH_O, send_doc}, + {"throw", _PyCFunction_CAST(gen_throw), METH_FASTCALL, throw_doc}, + {"close", gen_close, METH_NOARGS, close_doc}, {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, {NULL, NULL} /* Sentinel */ @@ -812,7 +840,7 @@ static PyAsyncMethods gen_as_async = { 0, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ - (sendfunc)PyGen_am_send, /* am_send */ + PyGen_am_send, /* am_send */ }; @@ -822,12 +850,12 @@ PyTypeObject PyGen_Type = { offsetof(PyGenObject, gi_iframe.localsplus), /* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ /* methods */ - (destructor)gen_dealloc, /* tp_dealloc */ + gen_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ &gen_as_async, /* tp_as_async */ - (reprfunc)gen_repr, /* tp_repr */ + gen_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -839,12 +867,12 @@ PyTypeObject PyGen_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)gen_traverse, /* tp_traverse */ + gen_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)gen_iternext, /* tp_iternext */ + gen_iternext, /* tp_iternext */ gen_methods, /* tp_methods */ gen_memberlist, /* tp_members */ gen_getsetlist, /* tp_getset */ @@ -903,17 +931,18 @@ _Py_MakeCoro(PyFunctionObject *func) return make_gen(&PyGen_Type, func); } if (coro_flags == CO_ASYNC_GENERATOR) { - PyAsyncGenObject *o; - o = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, func); - if (o == NULL) { + PyAsyncGenObject *ag; + ag = (PyAsyncGenObject *)make_gen(&PyAsyncGen_Type, func); + if (ag == NULL) { return NULL; } - o->ag_origin_or_finalizer = NULL; - o->ag_closed = 0; - o->ag_hooks_inited = 0; - o->ag_running_async = 0; - return (PyObject*)o; + ag->ag_origin_or_finalizer = NULL; + ag->ag_closed = 0; + ag->ag_hooks_inited = 0; + ag->ag_running_async = 0; + return (PyObject*)ag; } + assert (coro_flags == CO_COROUTINE); PyObject *coro = make_gen(&PyCoro_Type, func); if (!coro) { @@ -995,6 +1024,11 @@ typedef struct { PyCoroObject *cw_coroutine; } PyCoroWrapper; +#define _PyCoroWrapper_CAST(op) \ + (assert(Py_IS_TYPE((op), &_PyCoroWrapper_Type)), \ + _Py_CAST(PyCoroWrapper*, (op))) + + static int gen_is_coroutine(PyObject *o) { @@ -1057,14 +1091,15 @@ _PyCoro_GetAwaitableIter(PyObject *o) } static PyObject * -coro_repr(PyCoroObject *coro) +coro_repr(PyObject *self) { + PyCoroObject *coro = _PyCoroObject_CAST(self); return PyUnicode_FromFormat("", coro->cr_qualname, coro); } static PyObject * -coro_await(PyCoroObject *coro) +coro_await(PyObject *coro) { PyCoroWrapper *cw = PyObject_GC_New(PyCoroWrapper, &_PyCoroWrapper_Type); if (cw == NULL) { @@ -1076,7 +1111,7 @@ coro_await(PyCoroObject *coro) } static PyObject * -coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored)) +coro_get_cr_await(PyObject *coro, void *Py_UNUSED(ignored)) { PyObject *yf = _PyGen_yf((PyGenObject *) coro); if (yf == NULL) @@ -1085,8 +1120,9 @@ coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored)) } static PyObject * -cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored)) +cr_getsuspended(PyObject *self, void *Py_UNUSED(ignored)) { + PyCoroObject *coro = _PyCoroObject_CAST(self); if (FRAME_STATE_SUSPENDED(coro->cr_frame_state)) { Py_RETURN_TRUE; } @@ -1094,8 +1130,9 @@ cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored)) } static PyObject * -cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored)) +cr_getrunning(PyObject *self, void *Py_UNUSED(ignored)) { + PyCoroObject *coro = _PyCoroObject_CAST(self); if (coro->cr_frame_state == FRAME_EXECUTING) { Py_RETURN_TRUE; } @@ -1103,29 +1140,29 @@ cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored)) } static PyObject * -cr_getframe(PyCoroObject *coro, void *Py_UNUSED(ignored)) +cr_getframe(PyObject *coro, void *Py_UNUSED(ignored)) { - return _gen_getframe((PyGenObject *)coro, "cr_frame"); + return _gen_getframe(_PyGen_CAST(coro), "cr_frame"); } static PyObject * -cr_getcode(PyCoroObject *coro, void *Py_UNUSED(ignored)) +cr_getcode(PyObject *coro, void *Py_UNUSED(ignored)) { - return _gen_getcode((PyGenObject *)coro, "cr_code"); + return _gen_getcode(_PyGen_CAST(coro), "cr_code"); } static PyGetSetDef coro_getsetlist[] = { - {"__name__", (getter)gen_get_name, (setter)gen_set_name, + {"__name__", gen_get_name, gen_set_name, PyDoc_STR("name of the coroutine")}, - {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, + {"__qualname__", gen_get_qualname, gen_set_qualname, PyDoc_STR("qualified name of the coroutine")}, - {"cr_await", (getter)coro_get_cr_await, NULL, + {"cr_await", coro_get_cr_await, NULL, PyDoc_STR("object being awaited on, or None")}, - {"cr_running", (getter)cr_getrunning, NULL, NULL}, - {"cr_frame", (getter)cr_getframe, NULL, NULL}, - {"cr_code", (getter)cr_getcode, NULL, NULL}, - {"cr_suspended", (getter)cr_getsuspended, NULL, NULL}, + {"cr_running", cr_getrunning, NULL, NULL}, + {"cr_frame", cr_getframe, NULL, NULL}, + {"cr_code", cr_getcode, NULL, NULL}, + {"cr_suspended", cr_getsuspended, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -1152,19 +1189,19 @@ PyDoc_STRVAR(coro_close_doc, "close() -> raise GeneratorExit inside coroutine."); static PyMethodDef coro_methods[] = { - {"send",(PyCFunction)gen_send, METH_O, coro_send_doc}, + {"send", gen_send, METH_O, coro_send_doc}, {"throw",_PyCFunction_CAST(gen_throw), METH_FASTCALL, coro_throw_doc}, - {"close",(PyCFunction)gen_close, METH_NOARGS, coro_close_doc}, + {"close", gen_close, METH_NOARGS, coro_close_doc}, {"__sizeof__", (PyCFunction)gen_sizeof, METH_NOARGS, sizeof__doc__}, {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")}, {NULL, NULL} /* Sentinel */ }; static PyAsyncMethods coro_as_async = { - (unaryfunc)coro_await, /* am_await */ + coro_await, /* am_await */ 0, /* am_aiter */ 0, /* am_anext */ - (sendfunc)PyGen_am_send, /* am_send */ + PyGen_am_send, /* am_send */ }; PyTypeObject PyCoro_Type = { @@ -1173,12 +1210,12 @@ PyTypeObject PyCoro_Type = { offsetof(PyCoroObject, cr_iframe.localsplus),/* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ /* methods */ - (destructor)gen_dealloc, /* tp_dealloc */ + gen_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ &coro_as_async, /* tp_as_async */ - (reprfunc)coro_repr, /* tp_repr */ + coro_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -1190,7 +1227,7 @@ PyTypeObject PyCoro_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)gen_traverse, /* tp_traverse */ + gen_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyCoroObject, cr_weakreflist), /* tp_weaklistoffset */ @@ -1220,49 +1257,55 @@ PyTypeObject PyCoro_Type = { }; static void -coro_wrapper_dealloc(PyCoroWrapper *cw) +coro_wrapper_dealloc(PyObject *self) { + PyCoroWrapper *cw = _PyCoroWrapper_CAST(self); _PyObject_GC_UNTRACK((PyObject *)cw); Py_CLEAR(cw->cw_coroutine); PyObject_GC_Del(cw); } static PyObject * -coro_wrapper_iternext(PyCoroWrapper *cw) +coro_wrapper_iternext(PyObject *self) { - return gen_iternext((PyGenObject *)cw->cw_coroutine); + PyCoroWrapper *cw = _PyCoroWrapper_CAST(self); + return gen_iternext((PyObject *)cw->cw_coroutine); } static PyObject * -coro_wrapper_send(PyCoroWrapper *cw, PyObject *arg) +coro_wrapper_send(PyObject *self, PyObject *arg) { - return gen_send((PyGenObject *)cw->cw_coroutine, arg); + PyCoroWrapper *cw = _PyCoroWrapper_CAST(self); + return gen_send((PyObject *)cw->cw_coroutine, arg); } static PyObject * -coro_wrapper_throw(PyCoroWrapper *cw, PyObject *const *args, Py_ssize_t nargs) +coro_wrapper_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { + PyCoroWrapper *cw = _PyCoroWrapper_CAST(self); return gen_throw((PyGenObject *)cw->cw_coroutine, args, nargs); } static PyObject * -coro_wrapper_close(PyCoroWrapper *cw, PyObject *args) +coro_wrapper_close(PyObject *self, PyObject *args) { - return gen_close((PyGenObject *)cw->cw_coroutine, args); + PyCoroWrapper *cw = _PyCoroWrapper_CAST(self); + return gen_close((PyObject *)cw->cw_coroutine, args); } static int -coro_wrapper_traverse(PyCoroWrapper *cw, visitproc visit, void *arg) +coro_wrapper_traverse(PyObject *self, visitproc visit, void *arg) { + PyCoroWrapper *cw = _PyCoroWrapper_CAST(self); Py_VISIT((PyObject *)cw->cw_coroutine); return 0; } static PyMethodDef coro_wrapper_methods[] = { - {"send",(PyCFunction)coro_wrapper_send, METH_O, coro_send_doc}, - {"throw",_PyCFunction_CAST(coro_wrapper_throw), - METH_FASTCALL, coro_throw_doc}, - {"close",(PyCFunction)coro_wrapper_close, METH_NOARGS, coro_close_doc}, + {"send", coro_wrapper_send, METH_O, coro_send_doc}, + {"throw", _PyCFunction_CAST(coro_wrapper_throw), METH_FASTCALL, + coro_throw_doc}, + {"close", coro_wrapper_close, METH_NOARGS, coro_close_doc}, {NULL, NULL} /* Sentinel */ }; @@ -1271,7 +1314,7 @@ PyTypeObject _PyCoroWrapper_Type = { "coroutine_wrapper", sizeof(PyCoroWrapper), /* tp_basicsize */ 0, /* tp_itemsize */ - (destructor)coro_wrapper_dealloc, /* destructor tp_dealloc */ + coro_wrapper_dealloc, /* destructor tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -1288,12 +1331,12 @@ PyTypeObject _PyCoroWrapper_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ "A wrapper object implementing __await__ for coroutines.", - (traverseproc)coro_wrapper_traverse, /* tp_traverse */ + coro_wrapper_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)coro_wrapper_iternext, /* tp_iternext */ + coro_wrapper_iternext, /* tp_iternext */ coro_wrapper_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ @@ -1387,6 +1430,9 @@ typedef struct PyAsyncGenASend { AwaitableState ags_state; } PyAsyncGenASend; +#define _PyAsyncGenASend_CAST(op) \ + _Py_CAST(PyAsyncGenASend*, (op)) + typedef struct PyAsyncGenAThrow { PyObject_HEAD @@ -1408,19 +1454,24 @@ typedef struct _PyAsyncGenWrappedValue { #define _PyAsyncGenWrappedValue_CheckExact(o) \ Py_IS_TYPE(o, &_PyAsyncGenWrappedValue_Type) +#define _PyAsyncGenWrappedValue_CAST(op) \ + (assert(_PyAsyncGenWrappedValue_CheckExact(op)), \ + _Py_CAST(_PyAsyncGenWrappedValue*, (op))) static int -async_gen_traverse(PyAsyncGenObject *gen, visitproc visit, void *arg) +async_gen_traverse(PyObject *self, visitproc visit, void *arg) { - Py_VISIT(gen->ag_origin_or_finalizer); - return gen_traverse((PyGenObject*)gen, visit, arg); + PyAsyncGenObject *ag = _PyAsyncGenObject_CAST(self); + Py_VISIT(ag->ag_origin_or_finalizer); + return gen_traverse((PyObject*)ag, visit, arg); } static PyObject * -async_gen_repr(PyAsyncGenObject *o) +async_gen_repr(PyObject *self) { + PyAsyncGenObject *o = _PyAsyncGenObject_CAST(self); return PyUnicode_FromFormat("", o->ag_qualname, o); } @@ -1464,12 +1515,13 @@ async_gen_init_hooks(PyAsyncGenObject *o) static PyObject * -async_gen_anext(PyAsyncGenObject *o) +async_gen_anext(PyObject *self) { - if (async_gen_init_hooks(o)) { + PyAsyncGenObject *ag = _PyAsyncGenObject_CAST(self); + if (async_gen_init_hooks(ag)) { return NULL; } - return async_gen_asend_new(o, NULL); + return async_gen_asend_new(ag, NULL); } @@ -1510,20 +1562,21 @@ async_gen_athrow(PyAsyncGenObject *o, PyObject *args) } static PyObject * -ag_getframe(PyAsyncGenObject *ag, void *Py_UNUSED(ignored)) +ag_getframe(PyObject *ag, void *Py_UNUSED(ignored)) { return _gen_getframe((PyGenObject *)ag, "ag_frame"); } static PyObject * -ag_getcode(PyGenObject *gen, void *Py_UNUSED(ignored)) +ag_getcode(PyObject *gen, void *Py_UNUSED(ignored)) { - return _gen_getcode(gen, "ag_code"); + return _gen_getcode((PyGenObject*)gen, "ag_code"); } static PyObject * -ag_getsuspended(PyAsyncGenObject *ag, void *Py_UNUSED(ignored)) +ag_getsuspended(PyObject *self, void *Py_UNUSED(ignored)) { + PyAsyncGenObject *ag = _PyAsyncGenObject_CAST(self); if (FRAME_STATE_SUSPENDED(ag->ag_frame_state)) { Py_RETURN_TRUE; } @@ -1531,15 +1584,15 @@ ag_getsuspended(PyAsyncGenObject *ag, void *Py_UNUSED(ignored)) } static PyGetSetDef async_gen_getsetlist[] = { - {"__name__", (getter)gen_get_name, (setter)gen_set_name, + {"__name__", gen_get_name, gen_set_name, PyDoc_STR("name of the async generator")}, - {"__qualname__", (getter)gen_get_qualname, (setter)gen_set_qualname, + {"__qualname__", gen_get_qualname, gen_set_qualname, PyDoc_STR("qualified name of the async generator")}, - {"ag_await", (getter)coro_get_cr_await, NULL, + {"ag_await", coro_get_cr_await, NULL, PyDoc_STR("object being awaited on, or None")}, - {"ag_frame", (getter)ag_getframe, NULL, NULL}, - {"ag_code", (getter)ag_getcode, NULL, NULL}, - {"ag_suspended", (getter)ag_getsuspended, NULL, NULL}, + {"ag_frame", ag_getframe, NULL, NULL}, + {"ag_code", ag_getcode, NULL, NULL}, + {"ag_suspended", ag_getsuspended, NULL, NULL}, {NULL} /* Sentinel */ }; @@ -1577,8 +1630,8 @@ static PyMethodDef async_gen_methods[] = { static PyAsyncMethods async_gen_as_async = { 0, /* am_await */ PyObject_SelfIter, /* am_aiter */ - (unaryfunc)async_gen_anext, /* am_anext */ - (sendfunc)PyGen_am_send, /* am_send */ + async_gen_anext, /* am_anext */ + PyGen_am_send, /* am_send */ }; @@ -1588,12 +1641,12 @@ PyTypeObject PyAsyncGen_Type = { offsetof(PyAsyncGenObject, ag_iframe.localsplus), /* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ /* methods */ - (destructor)gen_dealloc, /* tp_dealloc */ + gen_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ &async_gen_as_async, /* tp_as_async */ - (reprfunc)async_gen_repr, /* tp_repr */ + async_gen_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -1605,7 +1658,7 @@ PyTypeObject PyAsyncGen_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)async_gen_traverse, /* tp_traverse */ + async_gen_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyAsyncGenObject, ag_weakreflist), /* tp_weaklistoffset */ @@ -1638,17 +1691,18 @@ PyTypeObject PyAsyncGen_Type = { PyObject * PyAsyncGen_New(PyFrameObject *f, PyObject *name, PyObject *qualname) { - PyAsyncGenObject *o; - o = (PyAsyncGenObject *)gen_new_with_qualname( - &PyAsyncGen_Type, f, name, qualname); - if (o == NULL) { + PyAsyncGenObject *ag; + ag = (PyAsyncGenObject *)gen_new_with_qualname(&PyAsyncGen_Type, f, + name, qualname); + if (ag == NULL) { return NULL; } - o->ag_origin_or_finalizer = NULL; - o->ag_closed = 0; - o->ag_hooks_inited = 0; - o->ag_running_async = 0; - return (PyObject*)o; + + ag->ag_origin_or_finalizer = NULL; + ag->ag_closed = 0; + ag->ag_hooks_inited = 0; + ag->ag_running_async = 0; + return (PyObject*)ag; } static PyObject * @@ -1685,36 +1739,38 @@ async_gen_unwrap_value(PyAsyncGenObject *gen, PyObject *result) static void -async_gen_asend_dealloc(PyAsyncGenASend *o) +async_gen_asend_dealloc(PyObject *self) { - if (PyObject_CallFinalizerFromDealloc((PyObject *)o)) { + assert(PyAsyncGenASend_CheckExact(self)); + PyAsyncGenASend *ags = _PyAsyncGenASend_CAST(self); + + if (PyObject_CallFinalizerFromDealloc(self)) { return; } - _PyObject_GC_UNTRACK((PyObject *)o); - Py_CLEAR(o->ags_gen); - Py_CLEAR(o->ags_sendval); + _PyObject_GC_UNTRACK(self); + Py_CLEAR(ags->ags_gen); + Py_CLEAR(ags->ags_sendval); - assert(PyAsyncGenASend_CheckExact(o)); - _PyGC_CLEAR_FINALIZED((PyObject *)o); + _PyGC_CLEAR_FINALIZED(self); - _Py_FREELIST_FREE(async_gen_asends, o, PyObject_GC_Del); + _Py_FREELIST_FREE(async_gen_asends, self, PyObject_GC_Del); } static int -async_gen_asend_traverse(PyAsyncGenASend *o, visitproc visit, void *arg) +async_gen_asend_traverse(PyObject *self, visitproc visit, void *arg) { - Py_VISIT(o->ags_gen); - Py_VISIT(o->ags_sendval); + PyAsyncGenASend *ags = _PyAsyncGenASend_CAST(self); + Py_VISIT(ags->ags_gen); + Py_VISIT(ags->ags_sendval); return 0; } static PyObject * -async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg) +async_gen_asend_send(PyObject *self, PyObject *arg) { - PyObject *result; - + PyAsyncGenASend *o = _PyAsyncGenASend_CAST(self); if (o->ags_state == AWAITABLE_STATE_CLOSED) { PyErr_SetString( PyExc_RuntimeError, @@ -1738,7 +1794,7 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg) } o->ags_gen->ag_running_async = 1; - result = gen_send((PyGenObject*)o->ags_gen, arg); + PyObject *result = gen_send((PyObject*)o->ags_gen, arg); result = async_gen_unwrap_value(o->ags_gen, result); if (result == NULL) { @@ -1750,16 +1806,16 @@ async_gen_asend_send(PyAsyncGenASend *o, PyObject *arg) static PyObject * -async_gen_asend_iternext(PyAsyncGenASend *o) +async_gen_asend_iternext(PyObject *ags) { - return async_gen_asend_send(o, NULL); + return async_gen_asend_send(ags, NULL); } static PyObject * -async_gen_asend_throw(PyAsyncGenASend *o, PyObject *const *args, Py_ssize_t nargs) +async_gen_asend_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - PyObject *result; + PyAsyncGenASend *o = _PyAsyncGenASend_CAST(self); if (o->ags_state == AWAITABLE_STATE_CLOSED) { PyErr_SetString( @@ -1781,7 +1837,7 @@ async_gen_asend_throw(PyAsyncGenASend *o, PyObject *const *args, Py_ssize_t narg o->ags_gen->ag_running_async = 1; } - result = gen_throw((PyGenObject*)o->ags_gen, args, nargs); + PyObject *result = gen_throw((PyGenObject*)o->ags_gen, args, nargs); result = async_gen_unwrap_value(o->ags_gen, result); if (result == NULL) { @@ -1794,13 +1850,14 @@ async_gen_asend_throw(PyAsyncGenASend *o, PyObject *const *args, Py_ssize_t narg static PyObject * -async_gen_asend_close(PyAsyncGenASend *o, PyObject *args) +async_gen_asend_close(PyObject *self, PyObject *args) { - PyObject *result; + PyAsyncGenASend *o = _PyAsyncGenASend_CAST(self); if (o->ags_state == AWAITABLE_STATE_CLOSED) { Py_RETURN_NONE; } - result = async_gen_asend_throw(o, &PyExc_GeneratorExit, 1); + + PyObject *result = async_gen_asend_throw(self, &PyExc_GeneratorExit, 1); if (result == NULL) { if (PyErr_ExceptionMatches(PyExc_StopIteration) || PyErr_ExceptionMatches(PyExc_StopAsyncIteration) || @@ -1810,25 +1867,26 @@ async_gen_asend_close(PyAsyncGenASend *o, PyObject *args) Py_RETURN_NONE; } return result; - } else { - Py_DECREF(result); - PyErr_SetString(PyExc_RuntimeError, "coroutine ignored GeneratorExit"); - return NULL; } + + Py_DECREF(result); + PyErr_SetString(PyExc_RuntimeError, "coroutine ignored GeneratorExit"); + return NULL; } static void -async_gen_asend_finalize(PyAsyncGenASend *o) +async_gen_asend_finalize(PyObject *self) { - if (o->ags_state == AWAITABLE_STATE_INIT) { - _PyErr_WarnUnawaitedAgenMethod(o->ags_gen, &_Py_ID(asend)); + PyAsyncGenASend *ags = _PyAsyncGenASend_CAST(self); + if (ags->ags_state == AWAITABLE_STATE_INIT) { + _PyErr_WarnUnawaitedAgenMethod(ags->ags_gen, &_Py_ID(asend)); } } static PyMethodDef async_gen_asend_methods[] = { - {"send", (PyCFunction)async_gen_asend_send, METH_O, send_doc}, + {"send", async_gen_asend_send, METH_O, send_doc}, {"throw", _PyCFunction_CAST(async_gen_asend_throw), METH_FASTCALL, throw_doc}, - {"close", (PyCFunction)async_gen_asend_close, METH_NOARGS, close_doc}, + {"close", async_gen_asend_close, METH_NOARGS, close_doc}, {NULL, NULL} /* Sentinel */ }; @@ -1847,7 +1905,7 @@ PyTypeObject _PyAsyncGenASend_Type = { sizeof(PyAsyncGenASend), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)async_gen_asend_dealloc, /* tp_dealloc */ + async_gen_asend_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -1864,12 +1922,12 @@ PyTypeObject _PyAsyncGenASend_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)async_gen_asend_traverse, /* tp_traverse */ + async_gen_asend_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)async_gen_asend_iternext, /* tp_iternext */ + async_gen_asend_iternext, /* tp_iternext */ async_gen_asend_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ @@ -1881,29 +1939,27 @@ PyTypeObject _PyAsyncGenASend_Type = { 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ - .tp_finalize = (destructor)async_gen_asend_finalize, + .tp_finalize = async_gen_asend_finalize, }; static PyObject * async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval) { - PyAsyncGenASend *o = _Py_FREELIST_POP(PyAsyncGenASend, async_gen_asends); - if (o == NULL) { - o = PyObject_GC_New(PyAsyncGenASend, &_PyAsyncGenASend_Type); - if (o == NULL) { + PyAsyncGenASend *ags = _Py_FREELIST_POP(PyAsyncGenASend, async_gen_asends); + if (ags == NULL) { + ags = PyObject_GC_New(PyAsyncGenASend, &_PyAsyncGenASend_Type); + if (ags == NULL) { return NULL; } } - o->ags_gen = (PyAsyncGenObject*)Py_NewRef(gen); - - o->ags_sendval = Py_XNewRef(sendval); + ags->ags_gen = (PyAsyncGenObject*)Py_NewRef(gen); + ags->ags_sendval = Py_XNewRef(sendval); + ags->ags_state = AWAITABLE_STATE_INIT; - o->ags_state = AWAITABLE_STATE_INIT; - - _PyObject_GC_TRACK((PyObject*)o); - return (PyObject*)o; + _PyObject_GC_TRACK((PyObject*)ags); + return (PyObject*)ags; } @@ -1911,19 +1967,20 @@ async_gen_asend_new(PyAsyncGenObject *gen, PyObject *sendval) static void -async_gen_wrapped_val_dealloc(_PyAsyncGenWrappedValue *o) +async_gen_wrapped_val_dealloc(PyObject *self) { - _PyObject_GC_UNTRACK((PyObject *)o); - Py_CLEAR(o->agw_val); - _Py_FREELIST_FREE(async_gens, o, PyObject_GC_Del); + _PyAsyncGenWrappedValue *agw = _PyAsyncGenWrappedValue_CAST(self); + _PyObject_GC_UNTRACK(self); + Py_CLEAR(agw->agw_val); + _Py_FREELIST_FREE(async_gens, self, PyObject_GC_Del); } static int -async_gen_wrapped_val_traverse(_PyAsyncGenWrappedValue *o, - visitproc visit, void *arg) +async_gen_wrapped_val_traverse(PyObject *self, visitproc visit, void *arg) { - Py_VISIT(o->agw_val); + _PyAsyncGenWrappedValue *agw = _PyAsyncGenWrappedValue_CAST(self); + Py_VISIT(agw->agw_val); return 0; } @@ -1934,7 +1991,7 @@ PyTypeObject _PyAsyncGenWrappedValue_Type = { sizeof(_PyAsyncGenWrappedValue), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)async_gen_wrapped_val_dealloc, /* tp_dealloc */ + async_gen_wrapped_val_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -1951,7 +2008,7 @@ PyTypeObject _PyAsyncGenWrappedValue_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)async_gen_wrapped_val_traverse, /* tp_traverse */ + async_gen_wrapped_val_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ @@ -1993,34 +2050,40 @@ _PyAsyncGenValueWrapperNew(PyThreadState *tstate, PyObject *val) /* ---------- Async Generator AThrow awaitable ------------ */ +#define _PyAsyncGenAThrow_CAST(op) \ + (assert(Py_IS_TYPE((op), &_PyAsyncGenAThrow_Type)), \ + _Py_CAST(PyAsyncGenAThrow*, (op))) static void -async_gen_athrow_dealloc(PyAsyncGenAThrow *o) +async_gen_athrow_dealloc(PyObject *self) { - if (PyObject_CallFinalizerFromDealloc((PyObject *)o)) { + PyAsyncGenAThrow *agt = _PyAsyncGenAThrow_CAST(self); + if (PyObject_CallFinalizerFromDealloc(self)) { return; } - _PyObject_GC_UNTRACK((PyObject *)o); - Py_CLEAR(o->agt_gen); - Py_CLEAR(o->agt_args); - PyObject_GC_Del(o); + _PyObject_GC_UNTRACK(self); + Py_CLEAR(agt->agt_gen); + Py_CLEAR(agt->agt_args); + PyObject_GC_Del(self); } static int -async_gen_athrow_traverse(PyAsyncGenAThrow *o, visitproc visit, void *arg) +async_gen_athrow_traverse(PyObject *self, visitproc visit, void *arg) { - Py_VISIT(o->agt_gen); - Py_VISIT(o->agt_args); + PyAsyncGenAThrow *agt = _PyAsyncGenAThrow_CAST(self); + Py_VISIT(agt->agt_gen); + Py_VISIT(agt->agt_args); return 0; } static PyObject * -async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) +async_gen_athrow_send(PyObject *self, PyObject *arg) { - PyGenObject *gen = (PyGenObject*)o->agt_gen; + PyAsyncGenAThrow *o = _PyAsyncGenAThrow_CAST(self); + PyGenObject *gen = _PyGen_CAST(o->agt_gen); PyObject *retval; if (o->agt_state == AWAITABLE_STATE_CLOSED) { @@ -2103,7 +2166,7 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) assert(o->agt_state == AWAITABLE_STATE_ITER); - retval = gen_send((PyGenObject *)gen, arg); + retval = gen_send((PyObject *)gen, arg); if (o->agt_args) { return async_gen_unwrap_value(o->agt_gen, retval); } else { @@ -2150,9 +2213,9 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) static PyObject * -async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t nargs) +async_gen_athrow_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs) { - PyObject *retval; + PyAsyncGenAThrow *o = _PyAsyncGenAThrow_CAST(self); if (o->agt_state == AWAITABLE_STATE_CLOSED) { PyErr_SetString( @@ -2181,7 +2244,7 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na o->agt_gen->ag_running_async = 1; } - retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs); + PyObject *retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs); if (o->agt_args) { retval = async_gen_unwrap_value(o->agt_gen, retval); if (retval == NULL) { @@ -2189,7 +2252,8 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na o->agt_state = AWAITABLE_STATE_CLOSED; } return retval; - } else { + } + else { /* aclose() mode */ if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) { o->agt_gen->ag_running_async = 0; @@ -2219,20 +2283,21 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na static PyObject * -async_gen_athrow_iternext(PyAsyncGenAThrow *o) +async_gen_athrow_iternext(PyObject *agt) { - return async_gen_athrow_send(o, Py_None); + return async_gen_athrow_send(agt, Py_None); } static PyObject * -async_gen_athrow_close(PyAsyncGenAThrow *o, PyObject *args) +async_gen_athrow_close(PyObject *self, PyObject *args) { - PyObject *result; - if (o->agt_state == AWAITABLE_STATE_CLOSED) { + PyAsyncGenAThrow *agt = _PyAsyncGenAThrow_CAST(self); + if (agt->agt_state == AWAITABLE_STATE_CLOSED) { Py_RETURN_NONE; } - result = async_gen_athrow_throw(o, &PyExc_GeneratorExit, 1); + PyObject *result = async_gen_athrow_throw((PyObject*)agt, + &PyExc_GeneratorExit, 1); if (result == NULL) { if (PyErr_ExceptionMatches(PyExc_StopIteration) || PyErr_ExceptionMatches(PyExc_StopAsyncIteration) || @@ -2260,10 +2325,10 @@ async_gen_athrow_finalize(PyAsyncGenAThrow *o) } static PyMethodDef async_gen_athrow_methods[] = { - {"send", (PyCFunction)async_gen_athrow_send, METH_O, send_doc}, + {"send", async_gen_athrow_send, METH_O, send_doc}, {"throw", _PyCFunction_CAST(async_gen_athrow_throw), METH_FASTCALL, throw_doc}, - {"close", (PyCFunction)async_gen_athrow_close, METH_NOARGS, close_doc}, + {"close", async_gen_athrow_close, METH_NOARGS, close_doc}, {NULL, NULL} /* Sentinel */ }; @@ -2282,7 +2347,7 @@ PyTypeObject _PyAsyncGenAThrow_Type = { sizeof(PyAsyncGenAThrow), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)async_gen_athrow_dealloc, /* tp_dealloc */ + async_gen_athrow_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -2299,12 +2364,12 @@ PyTypeObject _PyAsyncGenAThrow_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)async_gen_athrow_traverse, /* tp_traverse */ + async_gen_athrow_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)async_gen_athrow_iternext, /* tp_iternext */ + async_gen_athrow_iternext, /* tp_iternext */ async_gen_athrow_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ diff --git a/Objects/longobject.c b/Objects/longobject.c index 9beb5884a6932b..4e948940485730 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -31,6 +31,13 @@ class int "PyObject *" "&PyLong_Type" /* If defined, use algorithms from the _pylong.py module */ #define WITH_PYLONG_MODULE 1 +// Forward declarations +static PyLongObject* long_neg(PyLongObject *v); +static PyLongObject *x_divrem(PyLongObject *, PyLongObject *, PyLongObject **); +static PyObject* long_long(PyObject *v); +static PyObject* long_lshift_int64(PyLongObject *a, int64_t shiftby); + + static inline void _Py_DECREF_INT(PyLongObject *op) { @@ -266,17 +273,17 @@ _PyLong_FromLarge(stwodigits ival) } /* Create a new int object from a C word-sized int */ -static inline PyObject * +static inline PyLongObject * _PyLong_FromSTwoDigits(stwodigits x) { if (IS_SMALL_INT(x)) { - return get_small_int((sdigit)x); + return (PyLongObject*)get_small_int((sdigit)x); } assert(x != 0); if (is_medium_int(x)) { - return _PyLong_FromMedium((sdigit)x); + return (PyLongObject*)_PyLong_FromMedium((sdigit)x); } - return _PyLong_FromLarge(x); + return (PyLongObject*)_PyLong_FromLarge(x); } /* If a freshly-allocated int is already shared, it must @@ -292,7 +299,7 @@ _PyLong_Negate(PyLongObject **x_p) return; } - *x_p = (PyLongObject *)_PyLong_FromSTwoDigits(-medium_value(x)); + *x_p = _PyLong_FromSTwoDigits(-medium_value(x)); Py_DECREF(x); } @@ -2619,8 +2626,6 @@ long_from_binary_base(const char *start, const char *end, Py_ssize_t digits, int return 0; } -static PyObject *long_neg(PyLongObject *v); - #ifdef WITH_PYLONG_MODULE /* asymptotically faster str-to-long conversion for base 10, using _pylong.py */ static int @@ -3149,11 +3154,6 @@ PyLong_FromUnicodeObject(PyObject *u, int base) return NULL; } -/* forward */ -static PyLongObject *x_divrem - (PyLongObject *, PyLongObject *, PyLongObject **); -static PyObject *long_long(PyObject *v); - /* Int division with remainder, top-level routine */ static int @@ -3746,11 +3746,12 @@ x_sub(PyLongObject *a, PyLongObject *b) return maybe_small_long(long_normalize(z)); } -PyObject * -_PyLong_Add(PyLongObject *a, PyLongObject *b) +static PyLongObject * +long_add(PyLongObject *a, PyLongObject *b) { if (_PyLong_BothAreCompact(a, b)) { - return _PyLong_FromSTwoDigits(medium_value(a) + medium_value(b)); + stwodigits z = medium_value(a) + medium_value(b); + return _PyLong_FromSTwoDigits(z); } PyLongObject *z; @@ -3775,24 +3776,31 @@ _PyLong_Add(PyLongObject *a, PyLongObject *b) else z = x_add(a, b); } - return (PyObject *)z; + return z; +} + +PyObject * +_PyLong_Add(PyLongObject *a, PyLongObject *b) +{ + return (PyObject*)long_add(a, b); } static PyObject * -long_add(PyLongObject *a, PyLongObject *b) +long_add_method(PyObject *a, PyObject *b) { CHECK_BINOP(a, b); - return _PyLong_Add(a, b); + return (PyObject*)long_add((PyLongObject*)a, (PyLongObject*)b); } -PyObject * -_PyLong_Subtract(PyLongObject *a, PyLongObject *b) -{ - PyLongObject *z; +static PyLongObject * +long_sub(PyLongObject *a, PyLongObject *b) +{ if (_PyLong_BothAreCompact(a, b)) { return _PyLong_FromSTwoDigits(medium_value(a) - medium_value(b)); } + + PyLongObject *z; if (_PyLong_IsNegative(a)) { if (_PyLong_IsNegative(b)) { z = x_sub(b, a); @@ -3811,16 +3819,23 @@ _PyLong_Subtract(PyLongObject *a, PyLongObject *b) else z = x_sub(a, b); } - return (PyObject *)z; + return z; +} + +PyObject * +_PyLong_Subtract(PyLongObject *a, PyLongObject *b) +{ + return (PyObject*)long_sub(a, b); } static PyObject * -long_sub(PyLongObject *a, PyLongObject *b) +long_sub_method(PyObject *a, PyObject *b) { CHECK_BINOP(a, b); - return _PyLong_Subtract(a, b); + return (PyObject*)long_sub((PyLongObject*)a, (PyLongObject*)b); } + /* Grade school multiplication, ignoring the signs. * Returns the absolute value of the product, or NULL if error. */ @@ -4236,32 +4251,35 @@ k_lopsided_mul(PyLongObject *a, PyLongObject *b) return NULL; } -PyObject * -_PyLong_Multiply(PyLongObject *a, PyLongObject *b) -{ - PyLongObject *z; +static PyLongObject* +long_mul(PyLongObject *a, PyLongObject *b) +{ /* fast path for single-digit multiplication */ if (_PyLong_BothAreCompact(a, b)) { stwodigits v = medium_value(a) * medium_value(b); return _PyLong_FromSTwoDigits(v); } - z = k_mul(a, b); + PyLongObject *z = k_mul(a, b); /* Negate if exactly one of the inputs is negative. */ if (!_PyLong_SameSign(a, b) && z) { _PyLong_Negate(&z); - if (z == NULL) - return NULL; } - return (PyObject *)z; + return z; +} + +PyObject * +_PyLong_Multiply(PyLongObject *a, PyLongObject *b) +{ + return (PyObject*)long_mul(a, b); } static PyObject * -long_mul(PyLongObject *a, PyLongObject *b) +long_mul_method(PyObject *a, PyObject *b) { CHECK_BINOP(a, b); - return _PyLong_Multiply(a, b); + return (PyObject*)long_mul((PyLongObject*)a, (PyLongObject*)b); } /* Fast modulo division for single-digit longs. */ @@ -4416,13 +4434,13 @@ l_divmod(PyLongObject *v, PyLongObject *w, if ((_PyLong_IsNegative(mod) && _PyLong_IsPositive(w)) || (_PyLong_IsPositive(mod) && _PyLong_IsNegative(w))) { PyLongObject *temp; - temp = (PyLongObject *) long_add(mod, w); + temp = long_add(mod, w); Py_SETREF(mod, temp); if (mod == NULL) { Py_DECREF(div); return -1; } - temp = (PyLongObject *) long_sub(div, (PyLongObject *)_PyLong_GetOne()); + temp = long_sub(div, (PyLongObject *)_PyLong_GetOne()); if (temp == NULL) { Py_DECREF(mod); Py_DECREF(div); @@ -4463,7 +4481,7 @@ l_mod(PyLongObject *v, PyLongObject *w, PyLongObject **pmod) if ((_PyLong_IsNegative(mod) && _PyLong_IsPositive(w)) || (_PyLong_IsPositive(mod) && _PyLong_IsNegative(w))) { PyLongObject *temp; - temp = (PyLongObject *) long_add(mod, w); + temp = long_add(mod, w); Py_SETREF(mod, temp); if (mod == NULL) return -1; @@ -4810,21 +4828,12 @@ long_divmod(PyObject *a, PyObject *b) static PyLongObject * long_invmod(PyLongObject *a, PyLongObject *n) { - PyLongObject *b, *c; - /* Should only ever be called for positive n */ assert(_PyLong_IsPositive(n)); - b = (PyLongObject *)PyLong_FromLong(1L); - if (b == NULL) { - return NULL; - } - c = (PyLongObject *)PyLong_FromLong(0L); - if (c == NULL) { - Py_DECREF(b); - return NULL; - } Py_INCREF(a); + PyLongObject *b = (PyLongObject *)Py_NewRef(_PyLong_GetOne()); + PyLongObject *c = (PyLongObject *)Py_NewRef(_PyLong_GetZero()); Py_INCREF(n); /* references now owned: a, b, c, n */ @@ -4841,7 +4850,7 @@ long_invmod(PyLongObject *a, PyLongObject *n) if (t == NULL) { goto Error; } - s = (PyLongObject *)long_sub(b, t); + s = long_sub(b, t); Py_DECREF(t); if (s == NULL) { goto Error; @@ -5136,7 +5145,7 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) } if (negativeOutput && !_PyLong_IsZero(z)) { - temp = (PyLongObject *)long_sub(z, c); + temp = long_sub(z, c); if (temp == NULL) goto Error; Py_SETREF(z, temp); @@ -5159,13 +5168,15 @@ long_pow(PyObject *v, PyObject *w, PyObject *x) } static PyObject * -long_invert(PyLongObject *v) +long_invert(PyObject *self) { + PyLongObject *v = _PyLong_CAST(self); + /* Implement ~x as -(x+1) */ - PyLongObject *x; if (_PyLong_IsCompact(v)) - return _PyLong_FromSTwoDigits(~medium_value(v)); - x = (PyLongObject *) long_add(v, (PyLongObject *)_PyLong_GetOne()); + return (PyObject*)_PyLong_FromSTwoDigits(~medium_value(v)); + + PyLongObject *x = long_add(v, (PyLongObject *)_PyLong_GetOne()); if (x == NULL) return NULL; _PyLong_Negate(&x); @@ -5174,31 +5185,45 @@ long_invert(PyLongObject *v) return (PyObject *)x; } -static PyObject * +static PyLongObject * long_neg(PyLongObject *v) { - PyLongObject *z; - if (_PyLong_IsCompact(v)) + if (_PyLong_IsCompact(v)) { return _PyLong_FromSTwoDigits(-medium_value(v)); - z = (PyLongObject *)_PyLong_Copy(v); - if (z != NULL) + } + + PyLongObject *z = (PyLongObject *)_PyLong_Copy(v); + if (z != NULL) { _PyLong_FlipSign(z); - return (PyObject *)z; + } + return z; } static PyObject * +long_neg_method(PyObject *v) +{ + return (PyObject*)long_neg(_PyLong_CAST(v)); +} + +static PyLongObject* long_abs(PyLongObject *v) { if (_PyLong_IsNegative(v)) return long_neg(v); else - return long_long((PyObject *)v); + return (PyLongObject*)long_long((PyObject *)v); +} + +static PyObject * +long_abs_method(PyObject *v) +{ + return (PyObject*)long_abs(_PyLong_CAST(v)); } static int -long_bool(PyLongObject *v) +long_bool(PyObject *v) { - return !_PyLong_IsZero(v); + return !_PyLong_IsZero(_PyLong_CAST(v)); } /* Inner function for both long_rshift and _PyLong_Rshift, shifting an @@ -5224,7 +5249,7 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) m = medium_value(a); shift = wordshift == 0 ? remshift : PyLong_SHIFT; x = m < 0 ? ~(~m >> shift) : m >> shift; - return _PyLong_FromSTwoDigits(x); + return (PyObject*)_PyLong_FromSTwoDigits(x); } a_negative = _PyLong_IsNegative(a); @@ -5358,7 +5383,7 @@ long_lshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) stwodigits m = medium_value(a); // bypass undefined shift operator behavior stwodigits x = m < 0 ? -(-m << remshift) : m << remshift; - return _PyLong_FromSTwoDigits(x); + return (PyObject*)_PyLong_FromSTwoDigits(x); } oldsize = _PyLong_DigitCount(a); @@ -5388,40 +5413,40 @@ long_lshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) return (PyObject *) maybe_small_long(z); } + static PyObject * -long_lshift(PyObject *a, PyObject *b) +long_lshift_method(PyObject *aa, PyObject *bb) { - int64_t shiftby; - - CHECK_BINOP(a, b); + CHECK_BINOP(aa, bb); + PyLongObject *a = (PyLongObject*)aa; + PyLongObject *b = (PyLongObject*)bb; - if (_PyLong_IsNegative((PyLongObject *)b)) { + if (_PyLong_IsNegative(b)) { PyErr_SetString(PyExc_ValueError, "negative shift count"); return NULL; } - if (_PyLong_IsZero((PyLongObject *)a)) { + if (_PyLong_IsZero(a)) { return PyLong_FromLong(0); } - if (PyLong_AsInt64(b, &shiftby) < 0) { + + int64_t shiftby; + if (PyLong_AsInt64(bb, &shiftby) < 0) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { PyErr_SetString(PyExc_OverflowError, "too many digits in integer"); } return NULL; } - return _PyLong_Lshift(a, shiftby); + return long_lshift_int64(a, shiftby); } /* Return a << shiftby. */ -PyObject * -_PyLong_Lshift(PyObject *a, int64_t shiftby) +static PyObject * +long_lshift_int64(PyLongObject *a, int64_t shiftby) { - Py_ssize_t wordshift; - digit remshift; - - assert(PyLong_Check(a)); assert(shiftby >= 0); - if (_PyLong_IsZero((PyLongObject *)a)) { + + if (_PyLong_IsZero(a)) { return PyLong_FromLong(0); } #if PY_SSIZE_T_MAX <= INT64_MAX / PyLong_SHIFT @@ -5431,11 +5456,18 @@ _PyLong_Lshift(PyObject *a, int64_t shiftby) return NULL; } #endif - wordshift = (Py_ssize_t)(shiftby / PyLong_SHIFT); - remshift = (digit)(shiftby % PyLong_SHIFT); - return long_lshift1((PyLongObject *)a, wordshift, remshift); + Py_ssize_t wordshift = (Py_ssize_t)(shiftby / PyLong_SHIFT); + digit remshift = (digit)(shiftby % PyLong_SHIFT); + return long_lshift1(a, wordshift, remshift); } +PyObject * +_PyLong_Lshift(PyObject *a, int64_t shiftby) +{ + return long_lshift_int64(_PyLong_CAST(a), shiftby); +} + + /* Compute two's complement of digit vector a[0:m], writing result to z[0:m]. The digit vector a need not be normalized, but should not be entirely zero. a and z may point to the same digit vector. */ @@ -5583,7 +5615,7 @@ long_and(PyObject *a, PyObject *b) PyLongObject *x = (PyLongObject*)a; PyLongObject *y = (PyLongObject*)b; if (_PyLong_IsCompact(x) && _PyLong_IsCompact(y)) { - return _PyLong_FromSTwoDigits(medium_value(x) & medium_value(y)); + return (PyObject*)_PyLong_FromSTwoDigits(medium_value(x) & medium_value(y)); } return long_bitwise(x, '&', y); } @@ -5595,7 +5627,7 @@ long_xor(PyObject *a, PyObject *b) PyLongObject *x = (PyLongObject*)a; PyLongObject *y = (PyLongObject*)b; if (_PyLong_IsCompact(x) && _PyLong_IsCompact(y)) { - return _PyLong_FromSTwoDigits(medium_value(x) ^ medium_value(y)); + return (PyObject*)_PyLong_FromSTwoDigits(medium_value(x) ^ medium_value(y)); } return long_bitwise(x, '^', y); } @@ -5607,7 +5639,7 @@ long_or(PyObject *a, PyObject *b) PyLongObject *x = (PyLongObject*)a; PyLongObject *y = (PyLongObject*)b; if (_PyLong_IsCompact(x) && _PyLong_IsCompact(y)) { - return _PyLong_FromSTwoDigits(medium_value(x) | medium_value(y)); + return (PyObject*)_PyLong_FromSTwoDigits(medium_value(x) | medium_value(y)); } return long_bitwise(x, '|', y); } @@ -5641,10 +5673,10 @@ _PyLong_GCD(PyObject *aarg, PyObject *barg) } /* Initial reduction: make sure that 0 <= b <= a. */ - a = (PyLongObject *)long_abs(a); + a = long_abs(a); if (a == NULL) return NULL; - b = (PyLongObject *)long_abs(b); + b = long_abs(b); if (b == NULL) { Py_DECREF(a); return NULL; @@ -6026,12 +6058,11 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b) /* compare twice the remainder with the divisor, to see if we need to adjust the quotient and remainder */ - PyObject *one = _PyLong_GetOne(); // borrowed reference - twice_rem = long_lshift((PyObject *)rem, one); + twice_rem = long_lshift_int64(rem, 1); if (twice_rem == NULL) goto error; if (quo_is_neg) { - temp = long_neg((PyLongObject*)twice_rem); + temp = (PyObject*)long_neg((PyLongObject*)twice_rem); Py_SETREF(twice_rem, temp); if (twice_rem == NULL) goto error; @@ -6042,18 +6073,19 @@ _PyLong_DivmodNear(PyObject *a, PyObject *b) quo_is_odd = (quo->long_value.ob_digit[0] & 1) != 0; if ((_PyLong_IsNegative((PyLongObject *)b) ? cmp < 0 : cmp > 0) || (cmp == 0 && quo_is_odd)) { /* fix up quotient */ + PyObject *one = _PyLong_GetOne(); // borrowed reference if (quo_is_neg) - temp = long_sub(quo, (PyLongObject *)one); + temp = (PyObject*)long_sub(quo, (PyLongObject *)one); else - temp = long_add(quo, (PyLongObject *)one); + temp = (PyObject*)long_add(quo, (PyLongObject *)one); Py_SETREF(quo, (PyLongObject *)temp); if (quo == NULL) goto error; /* and remainder */ if (quo_is_neg) - temp = long_add(rem, (PyLongObject *)b); + temp = (PyObject*)long_add(rem, (PyLongObject *)b); else - temp = long_sub(rem, (PyLongObject *)b); + temp = (PyObject*)long_sub(rem, (PyLongObject *)b); Py_SETREF(rem, (PyLongObject *)temp); if (rem == NULL) goto error; @@ -6089,8 +6121,6 @@ static PyObject * int___round___impl(PyObject *self, PyObject *o_ndigits) /*[clinic end generated code: output=954fda6b18875998 input=30c2aec788263144]*/ { - PyObject *temp, *result, *ndigits; - /* To round an integer m to the nearest 10**n (n positive), we make use of * the divmod_near operation, defined by: * @@ -6108,7 +6138,7 @@ int___round___impl(PyObject *self, PyObject *o_ndigits) if (o_ndigits == Py_None) return long_long(self); - ndigits = _PyNumber_Index(o_ndigits); + PyObject *ndigits = _PyNumber_Index(o_ndigits); if (ndigits == NULL) return NULL; @@ -6119,12 +6149,12 @@ int___round___impl(PyObject *self, PyObject *o_ndigits) } /* result = self - divmod_near(self, 10 ** -ndigits)[1] */ - temp = long_neg((PyLongObject*)ndigits); + PyObject *temp = (PyObject*)long_neg((PyLongObject*)ndigits); Py_SETREF(ndigits, temp); if (ndigits == NULL) return NULL; - result = PyLong_FromLong(10L); + PyObject *result = PyLong_FromLong(10); if (result == NULL) { Py_DECREF(ndigits); return NULL; @@ -6141,8 +6171,8 @@ int___round___impl(PyObject *self, PyObject *o_ndigits) if (result == NULL) return NULL; - temp = long_sub((PyLongObject *)self, - (PyLongObject *)PyTuple_GET_ITEM(result, 1)); + temp = (PyObject*)long_sub((PyLongObject*)self, + (PyLongObject*)PyTuple_GET_ITEM(result, 1)); Py_SETREF(result, temp); return result; @@ -6475,18 +6505,18 @@ Base 0 means to interpret the base from the string as an integer literal.\n\ 4"); static PyNumberMethods long_as_number = { - (binaryfunc)long_add, /*nb_add*/ - (binaryfunc)long_sub, /*nb_subtract*/ - (binaryfunc)long_mul, /*nb_multiply*/ + long_add_method, /*nb_add*/ + long_sub_method, /*nb_subtract*/ + long_mul_method, /*nb_multiply*/ long_mod, /*nb_remainder*/ long_divmod, /*nb_divmod*/ long_pow, /*nb_power*/ - (unaryfunc)long_neg, /*nb_negative*/ + long_neg_method, /*nb_negative*/ long_long, /*tp_positive*/ - (unaryfunc)long_abs, /*tp_absolute*/ - (inquiry)long_bool, /*tp_bool*/ - (unaryfunc)long_invert, /*nb_invert*/ - long_lshift, /*nb_lshift*/ + long_abs_method, /*tp_absolute*/ + long_bool, /*tp_bool*/ + long_invert, /*nb_invert*/ + long_lshift_method, /*nb_lshift*/ long_rshift, /*nb_rshift*/ long_and, /*nb_and*/ long_xor, /*nb_xor*/ diff --git a/Objects/methodobject.c b/Objects/methodobject.c index d6773a264101dc..345da4607423cf 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -156,8 +156,9 @@ PyCMethod_GetClass(PyObject *op) /* Methods (the standard built-in methods, that is) */ static void -meth_dealloc(PyCFunctionObject *m) +meth_dealloc(PyObject *self) { + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); // The Py_TRASHCAN mechanism requires that we be able to // call PyObject_GC_UnTrack twice on an object. PyObject_GC_UnTrack(m); @@ -175,8 +176,9 @@ meth_dealloc(PyCFunctionObject *m) } static PyObject * -meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored)) +meth_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) { + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); if (m->m_self == NULL || PyModule_Check(m->m_self)) return PyUnicode_FromString(m->m_ml->ml_name); @@ -185,32 +187,35 @@ meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored)) } static PyMethodDef meth_methods[] = { - {"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL}, + {"__reduce__", meth_reduce, METH_NOARGS, NULL}, {NULL, NULL} }; static PyObject * -meth_get__text_signature__(PyCFunctionObject *m, void *closure) +meth_get__text_signature__(PyObject *self, void *closure) { + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc, m->m_ml->ml_flags); } static PyObject * -meth_get__doc__(PyCFunctionObject *m, void *closure) +meth_get__doc__(PyObject *self, void *closure) { + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); } static PyObject * -meth_get__name__(PyCFunctionObject *m, void *closure) +meth_get__name__(PyObject *self, void *closure) { + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); return PyUnicode_FromString(m->m_ml->ml_name); } static PyObject * -meth_get__qualname__(PyCFunctionObject *m, void *closure) +meth_get__qualname__(PyObject *self, void *closure) { /* If __self__ is a module or NULL, return m.__name__ (e.g. len.__qualname__ == 'len') @@ -220,14 +225,15 @@ meth_get__qualname__(PyCFunctionObject *m, void *closure) Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__ (e.g. [].append.__qualname__ == 'list.append') */ - PyObject *type, *type_qualname, *res; - if (m->m_self == NULL || PyModule_Check(m->m_self)) + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); + if (m->m_self == NULL || PyModule_Check(m->m_self)) { return PyUnicode_FromString(m->m_ml->ml_name); + } - type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self); + PyObject *type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self); - type_qualname = PyObject_GetAttr(type, &_Py_ID(__qualname__)); + PyObject *type_qualname = PyObject_GetAttr(type, &_Py_ID(__qualname__)); if (type_qualname == NULL) return NULL; @@ -238,14 +244,15 @@ meth_get__qualname__(PyCFunctionObject *m, void *closure) return NULL; } - res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name); + PyObject *res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name); Py_DECREF(type_qualname); return res; } static int -meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) +meth_traverse(PyObject *self, visitproc visit, void *arg) { + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); Py_VISIT(PyCFunction_GET_CLASS(m)); Py_VISIT(m->m_self); Py_VISIT(m->m_module); @@ -253,22 +260,22 @@ meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) } static PyObject * -meth_get__self__(PyCFunctionObject *m, void *closure) +meth_get__self__(PyObject *meth, void *closure) { - PyObject *self; - - self = PyCFunction_GET_SELF(m); - if (self == NULL) + PyCFunctionObject *m = _PyCFunctionObject_CAST(meth); + PyObject *self = PyCFunction_GET_SELF(m); + if (self == NULL) { self = Py_None; + } return Py_NewRef(self); } -static PyGetSetDef meth_getsets [] = { - {"__doc__", (getter)meth_get__doc__, NULL, NULL}, - {"__name__", (getter)meth_get__name__, NULL, NULL}, - {"__qualname__", (getter)meth_get__qualname__, NULL, NULL}, - {"__self__", (getter)meth_get__self__, NULL, NULL}, - {"__text_signature__", (getter)meth_get__text_signature__, NULL, NULL}, +static PyGetSetDef meth_getsets[] = { + {"__doc__", meth_get__doc__, NULL, NULL}, + {"__name__", meth_get__name__, NULL, NULL}, + {"__qualname__", meth_get__qualname__, NULL, NULL}, + {"__self__", meth_get__self__, NULL, NULL}, + {"__text_signature__", meth_get__text_signature__, NULL, NULL}, {0} }; @@ -280,15 +287,18 @@ static PyMemberDef meth_members[] = { }; static PyObject * -meth_repr(PyCFunctionObject *m) +meth_repr(PyObject *self) { - if (m->m_self == NULL || PyModule_Check(m->m_self)) + PyCFunctionObject *m = _PyCFunctionObject_CAST(self); + if (m->m_self == NULL || PyModule_Check(m->m_self)) { return PyUnicode_FromFormat("", - m->m_ml->ml_name); + m->m_ml->ml_name); + } + return PyUnicode_FromFormat("", - m->m_ml->ml_name, - Py_TYPE(m->m_self)->tp_name, - m->m_self); + m->m_ml->ml_name, + Py_TYPE(m->m_self)->tp_name, + m->m_self); } static PyObject * @@ -317,14 +327,15 @@ meth_richcompare(PyObject *self, PyObject *other, int op) } static Py_hash_t -meth_hash(PyCFunctionObject *a) +meth_hash(PyObject *self) { - Py_hash_t x, y; - x = PyObject_GenericHash(a->m_self); - y = _Py_HashPointer((void*)(a->m_ml->ml_meth)); + PyCFunctionObject *a = _PyCFunctionObject_CAST(self); + Py_hash_t x = PyObject_GenericHash(a->m_self); + Py_hash_t y = _Py_HashPointer((void*)(a->m_ml->ml_meth)); x ^= y; - if (x == -1) + if (x == -1) { x = -2; + } return x; } @@ -334,16 +345,16 @@ PyTypeObject PyCFunction_Type = { "builtin_function_or_method", sizeof(PyCFunctionObject), 0, - (destructor)meth_dealloc, /* tp_dealloc */ + meth_dealloc, /* tp_dealloc */ offsetof(PyCFunctionObject, vectorcall), /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)meth_repr, /* tp_repr */ + meth_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ - (hashfunc)meth_hash, /* tp_hash */ + meth_hash, /* tp_hash */ cfunction_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -352,7 +363,7 @@ PyTypeObject PyCFunction_Type = { Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)meth_traverse, /* tp_traverse */ + meth_traverse, /* tp_traverse */ 0, /* tp_clear */ meth_richcompare, /* tp_richcompare */ offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */ diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index efc74dafb5fc73..f63ae4e048bcd9 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -15,6 +15,10 @@ #include "osdefs.h" // MAXPATHLEN +#define _PyModule_CAST(op) \ + (assert(PyModule_Check(op)), _Py_CAST(PyModuleObject*, (op))) + + static PyMemberDef module_members[] = { {"__dict__", _Py_T_OBJECT, offsetof(PyModuleObject, md_dict), Py_READONLY}, {0} @@ -225,7 +229,9 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version) return NULL; } name = _PyImport_ResolveNameWithPackageContext(name); - if ((m = (PyModuleObject*)PyModule_New(name)) == NULL) + + m = (PyModuleObject*)PyModule_New(name); + if (m == NULL) return NULL; if (module->m_size > 0) { @@ -758,22 +764,26 @@ module___init___impl(PyModuleObject *self, PyObject *name, PyObject *doc) } static void -module_dealloc(PyModuleObject *m) +module_dealloc(PyObject *self) { - int verbose = _Py_GetConfig()->verbose; + PyModuleObject *m = _PyModule_CAST(self); PyObject_GC_UnTrack(m); + + int verbose = _Py_GetConfig()->verbose; if (verbose && m->md_name) { PySys_FormatStderr("# destroy %U\n", m->md_name); } if (m->md_weaklist != NULL) PyObject_ClearWeakRefs((PyObject *) m); + /* bpo-39824: Don't call m_free() if m_size > 0 and md_state=NULL */ if (m->md_def && m->md_def->m_free && (m->md_def->m_size <= 0 || m->md_state != NULL)) { m->md_def->m_free(m); } + Py_XDECREF(m->md_dict); Py_XDECREF(m->md_name); if (m->md_state != NULL) @@ -782,8 +792,9 @@ module_dealloc(PyModuleObject *m) } static PyObject * -module_repr(PyModuleObject *m) +module_repr(PyObject *self) { + PyModuleObject *m = _PyModule_CAST(self); PyInterpreterState *interp = _PyInterpreterState_GET(); return _PyImport_ImportlibModuleRepr(interp, (PyObject *)m); } @@ -1062,14 +1073,17 @@ _Py_module_getattro_impl(PyModuleObject *m, PyObject *name, int suppress) PyObject* -_Py_module_getattro(PyModuleObject *m, PyObject *name) +_Py_module_getattro(PyObject *self, PyObject *name) { + PyModuleObject *m = _PyModule_CAST(self); return _Py_module_getattro_impl(m, name, 0); } static int -module_traverse(PyModuleObject *m, visitproc visit, void *arg) +module_traverse(PyObject *self, visitproc visit, void *arg) { + PyModuleObject *m = _PyModule_CAST(self); + /* bpo-39824: Don't call m_traverse() if m_size > 0 and md_state=NULL */ if (m->md_def && m->md_def->m_traverse && (m->md_def->m_size <= 0 || m->md_state != NULL)) @@ -1078,13 +1092,16 @@ module_traverse(PyModuleObject *m, visitproc visit, void *arg) if (res) return res; } + Py_VISIT(m->md_dict); return 0; } static int -module_clear(PyModuleObject *m) +module_clear(PyObject *self) { + PyModuleObject *m = _PyModule_CAST(self); + /* bpo-39824: Don't call m_clear() if m_size > 0 and md_state=NULL */ if (m->md_def && m->md_def->m_clear && (m->md_def->m_size <= 0 || m->md_state != NULL)) @@ -1149,8 +1166,10 @@ module_get_dict(PyModuleObject *m) } static PyObject * -module_get_annotate(PyModuleObject *m, void *Py_UNUSED(ignored)) +module_get_annotate(PyObject *self, void *Py_UNUSED(ignored)) { + PyModuleObject *m = _PyModule_CAST(self); + PyObject *dict = module_get_dict(m); if (dict == NULL) { return NULL; @@ -1168,12 +1187,14 @@ module_get_annotate(PyModuleObject *m, void *Py_UNUSED(ignored)) } static int -module_set_annotate(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignored)) +module_set_annotate(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { + PyModuleObject *m = _PyModule_CAST(self); if (value == NULL) { PyErr_SetString(PyExc_TypeError, "cannot delete __annotate__ attribute"); return -1; } + PyObject *dict = module_get_dict(m); if (dict == NULL) { return -1; @@ -1200,8 +1221,10 @@ module_set_annotate(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignored) } static PyObject * -module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored)) +module_get_annotations(PyObject *self, void *Py_UNUSED(ignored)) { + PyModuleObject *m = _PyModule_CAST(self); + PyObject *dict = module_get_dict(m); if (dict == NULL) { return NULL; @@ -1249,14 +1272,16 @@ module_get_annotations(PyModuleObject *m, void *Py_UNUSED(ignored)) } static int -module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignored)) +module_set_annotations(PyObject *self, PyObject *value, void *Py_UNUSED(ignored)) { - int ret = -1; + PyModuleObject *m = _PyModule_CAST(self); + PyObject *dict = module_get_dict(m); if (dict == NULL) { return -1; } + int ret = -1; if (value != NULL) { /* set */ ret = PyDict_SetItem(dict, &_Py_ID(__annotations__), value); @@ -1282,8 +1307,8 @@ module_set_annotations(PyModuleObject *m, PyObject *value, void *Py_UNUSED(ignor static PyGetSetDef module_getsets[] = { - {"__annotations__", (getter)module_get_annotations, (setter)module_set_annotations}, - {"__annotate__", (getter)module_get_annotate, (setter)module_set_annotate}, + {"__annotations__", module_get_annotations, module_set_annotations}, + {"__annotate__", module_get_annotate, module_set_annotate}, {NULL} }; @@ -1292,26 +1317,26 @@ PyTypeObject PyModule_Type = { "module", /* tp_name */ sizeof(PyModuleObject), /* tp_basicsize */ 0, /* tp_itemsize */ - (destructor)module_dealloc, /* tp_dealloc */ + module_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)module_repr, /* tp_repr */ + module_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - (getattrofunc)_Py_module_getattro, /* tp_getattro */ + _Py_module_getattro, /* tp_getattro */ PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ module___init____doc__, /* tp_doc */ - (traverseproc)module_traverse, /* tp_traverse */ - (inquiry)module_clear, /* tp_clear */ + module_traverse, /* tp_traverse */ + module_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyModuleObject, md_weaklist), /* tp_weaklistoffset */ 0, /* tp_iter */ diff --git a/Objects/setobject.c b/Objects/setobject.c index c5f96d25585fa4..8bff4d99f81b81 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -404,8 +404,9 @@ set_empty_to_minsize(PySetObject *so) } static int -set_clear_internal(PySetObject *so) +set_clear_internal(PyObject *self) { + PySetObject *so = _PySet_CAST(self); setentry *entry; setentry *table = so->table; Py_ssize_t fill = so->fill; @@ -490,8 +491,9 @@ set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr) } static void -set_dealloc(PySetObject *so) +set_dealloc(PyObject *self) { + PySetObject *so = _PySet_CAST(self); setentry *entry; Py_ssize_t used = so->used; @@ -559,8 +561,9 @@ set_repr_lock_held(PySetObject *so) } static PyObject * -set_repr(PySetObject *so) +set_repr(PyObject *self) { + PySetObject *so = _PySet_CAST(self); PyObject *result; Py_BEGIN_CRITICAL_SECTION(so); result = set_repr_lock_held(so); @@ -569,8 +572,9 @@ set_repr(PySetObject *so) } static Py_ssize_t -set_len(PySetObject *so) +set_len(PyObject *self) { + PySetObject *so = _PySet_CAST(self); return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used); } @@ -584,11 +588,10 @@ set_merge_lock_held(PySetObject *so, PyObject *otherset) setentry *other_entry; assert (PyAnySet_Check(so)); - assert (PyAnySet_Check(otherset)); _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so); _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset); - other = (PySetObject*)otherset; + other = _PySet_CAST(otherset); if (other == so || other->used == 0) /* a.update(a) or a.update(set()); nothing to do */ return 0; @@ -684,8 +687,9 @@ set_pop_impl(PySetObject *so) } static int -set_traverse(PySetObject *so, visitproc visit, void *arg) +set_traverse(PyObject *self, visitproc visit, void *arg) { + PySetObject *so = _PySet_CAST(self); Py_ssize_t pos = 0; setentry *entry; @@ -718,8 +722,7 @@ _shuffle_bits(Py_uhash_t h) static Py_hash_t frozenset_hash_impl(PyObject *self) { - assert(PyAnySet_Check(self)); - PySetObject *so = (PySetObject *)self; + PySetObject *so = _PySet_CAST(self); Py_uhash_t hash = 0; setentry *entry; @@ -761,7 +764,7 @@ frozenset_hash_impl(PyObject *self) static Py_hash_t frozenset_hash(PyObject *self) { - PySetObject *so = (PySetObject *)self; + PySetObject *so = _PySet_CAST(self); Py_uhash_t hash; if (so->hash != -1) { @@ -784,8 +787,9 @@ typedef struct { } setiterobject; static void -setiter_dealloc(setiterobject *si) +setiter_dealloc(PyObject *self) { + setiterobject *si = (setiterobject*)self; /* bpo-31095: UnTrack is needed before calling any callbacks */ _PyObject_GC_UNTRACK(si); Py_XDECREF(si->si_set); @@ -793,8 +797,9 @@ setiter_dealloc(setiterobject *si) } static int -setiter_traverse(setiterobject *si, visitproc visit, void *arg) +setiter_traverse(PyObject *self, visitproc visit, void *arg) { + setiterobject *si = (setiterobject*)self; Py_VISIT(si->si_set); return 0; } @@ -810,8 +815,6 @@ setiter_len(setiterobject *si, PyObject *Py_UNUSED(ignored)) PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); -static PyObject *setiter_iternext(setiterobject *si); - static PyObject * setiter_reduce(setiterobject *si, PyObject *Py_UNUSED(ignored)) { @@ -836,8 +839,9 @@ static PyMethodDef setiter_methods[] = { {NULL, NULL} /* sentinel */ }; -static PyObject *setiter_iternext(setiterobject *si) +static PyObject *setiter_iternext(PyObject *self) { + setiterobject *si = (setiterobject*)self; PyObject *key = NULL; Py_ssize_t i, mask; setentry *entry; @@ -884,7 +888,7 @@ PyTypeObject PySetIter_Type = { sizeof(setiterobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)setiter_dealloc, /* tp_dealloc */ + setiter_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -901,18 +905,18 @@ PyTypeObject PySetIter_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)setiter_traverse, /* tp_traverse */ + setiter_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ PyObject_SelfIter, /* tp_iter */ - (iternextfunc)setiter_iternext, /* tp_iternext */ + setiter_iternext, /* tp_iternext */ setiter_methods, /* tp_methods */ 0, }; static PyObject * -set_iter(PySetObject *so) +set_iter(PyObject *so) { Py_ssize_t size = set_len(so); setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type); @@ -1270,7 +1274,7 @@ static PyObject * set_clear_impl(PySetObject *so) /*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/ { - set_clear_internal(so); + set_clear_internal((PyObject*)so); Py_RETURN_NONE; } @@ -1307,12 +1311,13 @@ set_union_impl(PySetObject *so, PyObject *args) } static PyObject * -set_or(PySetObject *so, PyObject *other) +set_or(PyObject *self, PyObject *other) { PySetObject *result; - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) + if (!PyAnySet_Check(self) || !PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); result = (PySetObject *)set_copy(so, NULL); if (result == NULL) { @@ -1329,10 +1334,11 @@ set_or(PySetObject *so, PyObject *other) } static PyObject * -set_ior(PySetObject *so, PyObject *other) +set_ior(PyObject *self, PyObject *other) { if (!PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); if (set_update_internal(so, other)) { return NULL; @@ -1495,10 +1501,11 @@ set_intersection_update_multi_impl(PySetObject *so, PyObject *args) } static PyObject * -set_and(PySetObject *so, PyObject *other) +set_and(PyObject *self, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) + if (!PyAnySet_Check(self) || !PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); PyObject *rv; Py_BEGIN_CRITICAL_SECTION2(so, other); @@ -1509,12 +1516,13 @@ set_and(PySetObject *so, PyObject *other) } static PyObject * -set_iand(PySetObject *so, PyObject *other) +set_iand(PyObject *self, PyObject *other) { PyObject *result; if (!PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); Py_BEGIN_CRITICAL_SECTION2(so, other); result = set_intersection_update(so, other); @@ -1603,7 +1611,7 @@ set_difference_update_internal(PySetObject *so, PyObject *other) _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other); if ((PyObject *)so == other) - return set_clear_internal(so); + return set_clear_internal((PyObject*)so); if (PyAnySet_Check(other)) { setentry *entry; @@ -1815,10 +1823,11 @@ set_difference_multi_impl(PySetObject *so, PyObject *args) } static PyObject * -set_sub(PySetObject *so, PyObject *other) +set_sub(PyObject *self, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) + if (!PyAnySet_Check(self) || !PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); PyObject *rv; Py_BEGIN_CRITICAL_SECTION2(so, other); @@ -1828,10 +1837,11 @@ set_sub(PySetObject *so, PyObject *other) } static PyObject * -set_isub(PySetObject *so, PyObject *other) +set_isub(PyObject *self, PyObject *other) { if (!PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); int rv; Py_BEGIN_CRITICAL_SECTION2(so, other); @@ -1973,20 +1983,23 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other) } static PyObject * -set_xor(PySetObject *so, PyObject *other) +set_xor(PyObject *self, PyObject *other) { - if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) + if (!PyAnySet_Check(self) || !PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); return set_symmetric_difference(so, other); } static PyObject * -set_ixor(PySetObject *so, PyObject *other) +set_ixor(PyObject *self, PyObject *other) { PyObject *result; if (!PyAnySet_Check(other)) Py_RETURN_NOTIMPLEMENTED; + PySetObject *so = _PySet_CAST(self); + result = set_symmetric_difference_update(so, other); if (result == NULL) return NULL; @@ -2081,8 +2094,9 @@ set_issuperset_impl(PySetObject *so, PyObject *other) } static PyObject * -set_richcompare(PySetObject *v, PyObject *w, int op) +set_richcompare(PyObject *self, PyObject *w, int op) { + PySetObject *v = _PySet_CAST(self); PyObject *r1; int r2; @@ -2099,7 +2113,7 @@ set_richcompare(PySetObject *v, PyObject *w, int op) Py_RETURN_FALSE; return set_issubset(v, w); case Py_NE: - r1 = set_richcompare(v, w, Py_EQ); + r1 = set_richcompare((PyObject*)v, w, Py_EQ); if (r1 == NULL) return NULL; r2 = PyObject_IsTrue(r1); @@ -2173,6 +2187,13 @@ _PySet_Contains(PySetObject *so, PyObject *key) return rv; } +static int +set_contains(PyObject *self, PyObject *key) +{ + PySetObject *so = _PySet_CAST(self); + return _PySet_Contains(so, key); +} + /*[clinic input] @critical_section @coexist @@ -2321,8 +2342,9 @@ set___sizeof___impl(PySetObject *so) } static int -set_init(PySetObject *self, PyObject *args, PyObject *kwds) +set_init(PyObject *so, PyObject *args, PyObject *kwds) { + PySetObject *self = _PySet_CAST(so); PyObject *iterable = NULL; if (!_PyArg_NoKeywords("set", kwds)) @@ -2339,7 +2361,7 @@ set_init(PySetObject *self, PyObject *args, PyObject *kwds) } Py_BEGIN_CRITICAL_SECTION(self); if (self->fill) - set_clear_internal(self); + set_clear_internal((PyObject*)self); self->hash = -1; Py_END_CRITICAL_SECTION(); @@ -2371,14 +2393,14 @@ set_vectorcall(PyObject *type, PyObject * const*args, } static PySequenceMethods set_as_sequence = { - (lenfunc)set_len, /* sq_length */ + set_len, /* sq_length */ 0, /* sq_concat */ 0, /* sq_repeat */ 0, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)_PySet_Contains, /* sq_contains */ + set_contains, /* sq_contains */ }; /* set object ********************************************************/ @@ -2410,7 +2432,7 @@ static PyMethodDef set_methods[] = { static PyNumberMethods set_as_number = { 0, /*nb_add*/ - (binaryfunc)set_sub, /*nb_subtract*/ + set_sub, /*nb_subtract*/ 0, /*nb_multiply*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ @@ -2422,22 +2444,22 @@ static PyNumberMethods set_as_number = { 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ - (binaryfunc)set_and, /*nb_and*/ - (binaryfunc)set_xor, /*nb_xor*/ - (binaryfunc)set_or, /*nb_or*/ + set_and, /*nb_and*/ + set_xor, /*nb_xor*/ + set_or, /*nb_or*/ 0, /*nb_int*/ 0, /*nb_reserved*/ 0, /*nb_float*/ 0, /*nb_inplace_add*/ - (binaryfunc)set_isub, /*nb_inplace_subtract*/ + set_isub, /*nb_inplace_subtract*/ 0, /*nb_inplace_multiply*/ 0, /*nb_inplace_remainder*/ 0, /*nb_inplace_power*/ 0, /*nb_inplace_lshift*/ 0, /*nb_inplace_rshift*/ - (binaryfunc)set_iand, /*nb_inplace_and*/ - (binaryfunc)set_ixor, /*nb_inplace_xor*/ - (binaryfunc)set_ior, /*nb_inplace_or*/ + set_iand, /*nb_inplace_and*/ + set_ixor, /*nb_inplace_xor*/ + set_ior, /*nb_inplace_or*/ }; PyDoc_STRVAR(set_doc, @@ -2452,12 +2474,12 @@ PyTypeObject PySet_Type = { sizeof(PySetObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)set_dealloc, /* tp_dealloc */ + set_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)set_repr, /* tp_repr */ + set_repr, /* tp_repr */ &set_as_number, /* tp_as_number */ &set_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -2469,13 +2491,13 @@ PyTypeObject PySet_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | - _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ + _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ set_doc, /* tp_doc */ - (traverseproc)set_traverse, /* tp_traverse */ - (inquiry)set_clear_internal, /* tp_clear */ - (richcmpfunc)set_richcompare, /* tp_richcompare */ + set_traverse, /* tp_traverse */ + set_clear_internal, /* tp_clear */ + set_richcompare, /* tp_richcompare */ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)set_iter, /* tp_iter */ + set_iter, /* tp_iter */ 0, /* tp_iternext */ set_methods, /* tp_methods */ 0, /* tp_members */ @@ -2485,7 +2507,7 @@ PyTypeObject PySet_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)set_init, /* tp_init */ + set_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ set_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ @@ -2513,7 +2535,7 @@ static PyMethodDef frozenset_methods[] = { static PyNumberMethods frozenset_as_number = { 0, /*nb_add*/ - (binaryfunc)set_sub, /*nb_subtract*/ + set_sub, /*nb_subtract*/ 0, /*nb_multiply*/ 0, /*nb_remainder*/ 0, /*nb_divmod*/ @@ -2525,9 +2547,9 @@ static PyNumberMethods frozenset_as_number = { 0, /*nb_invert*/ 0, /*nb_lshift*/ 0, /*nb_rshift*/ - (binaryfunc)set_and, /*nb_and*/ - (binaryfunc)set_xor, /*nb_xor*/ - (binaryfunc)set_or, /*nb_or*/ + set_and, /*nb_and*/ + set_xor, /*nb_xor*/ + set_or, /*nb_or*/ }; PyDoc_STRVAR(frozenset_doc, @@ -2542,12 +2564,12 @@ PyTypeObject PyFrozenSet_Type = { sizeof(PySetObject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ - (destructor)set_dealloc, /* tp_dealloc */ + set_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)set_repr, /* tp_repr */ + set_repr, /* tp_repr */ &frozenset_as_number, /* tp_as_number */ &set_as_sequence, /* tp_as_sequence */ 0, /* tp_as_mapping */ @@ -2559,13 +2581,13 @@ PyTypeObject PyFrozenSet_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | - _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ + _Py_TPFLAGS_MATCH_SELF, /* tp_flags */ frozenset_doc, /* tp_doc */ - (traverseproc)set_traverse, /* tp_traverse */ - (inquiry)set_clear_internal, /* tp_clear */ - (richcmpfunc)set_richcompare, /* tp_richcompare */ + set_traverse, /* tp_traverse */ + set_clear_internal, /* tp_clear */ + set_richcompare, /* tp_richcompare */ offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ - (getiterfunc)set_iter, /* tp_iter */ + set_iter, /* tp_iter */ 0, /* tp_iternext */ frozenset_methods, /* tp_methods */ 0, /* tp_members */ @@ -2604,7 +2626,7 @@ PySet_Size(PyObject *anyset) PyErr_BadInternalCall(); return -1; } - return set_len((PySetObject *)anyset); + return set_len(anyset); } int @@ -2621,7 +2643,7 @@ PySet_Clear(PyObject *set) void _PySet_ClearInternal(PySetObject *so) { - (void)set_clear_internal(so); + (void)set_clear_internal((PyObject*)so); } int diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 1b6d35998c2b69..4fef0af93fe095 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -343,7 +343,7 @@ Create a slice object. This is used for extended slicing (e.g. a[0:10:2])."); static void slice_dealloc(PySliceObject *r) { - _PyObject_GC_UNTRACK(r); + PyObject_GC_UnTrack(r); Py_DECREF(r->step); Py_DECREF(r->start); Py_DECREF(r->stop); diff --git a/Objects/stringlib/eq.h b/Objects/stringlib/eq.h index 2eac4baf5ca9ce..821b692f26b830 100644 --- a/Objects/stringlib/eq.h +++ b/Objects/stringlib/eq.h @@ -4,14 +4,19 @@ * unicode_eq() is called when the hash of two unicode objects is equal. */ Py_LOCAL_INLINE(int) -unicode_eq(PyObject *a, PyObject *b) +unicode_eq(PyObject *str1, PyObject *str2) { - if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b)) + Py_ssize_t len = PyUnicode_GET_LENGTH(str1); + if (PyUnicode_GET_LENGTH(str2) != len) { return 0; - if (PyUnicode_GET_LENGTH(a) == 0) - return 1; - if (PyUnicode_KIND(a) != PyUnicode_KIND(b)) + } + + int kind = PyUnicode_KIND(str1); + if (PyUnicode_KIND(str2) != kind) { return 0; - return memcmp(PyUnicode_1BYTE_DATA(a), PyUnicode_1BYTE_DATA(b), - PyUnicode_GET_LENGTH(a) * PyUnicode_KIND(a)) == 0; + } + + const void *data1 = PyUnicode_DATA(str1); + const void *data2 = PyUnicode_DATA(str2); + return (memcmp(data1, data2, len * kind) == 0); } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 4d8cca68df946a..47134697918052 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -181,8 +181,9 @@ PyTuple_Pack(Py_ssize_t n, ...) /* Methods */ static void -tupledealloc(PyTupleObject *op) +tuple_dealloc(PyObject *self) { + PyTupleObject *op = _PyTuple_CAST(self); if (Py_SIZE(op) == 0) { /* The empty tuple is statically allocated. */ if (op == &_Py_SINGLETON(tuple_empty)) { @@ -199,7 +200,7 @@ tupledealloc(PyTupleObject *op) } PyObject_GC_UnTrack(op); - Py_TRASHCAN_BEGIN(op, tupledealloc) + Py_TRASHCAN_BEGIN(op, tuple_dealloc) Py_ssize_t i = Py_SIZE(op); while (--i >= 0) { @@ -214,29 +215,29 @@ tupledealloc(PyTupleObject *op) } static PyObject * -tuplerepr(PyTupleObject *v) +tuple_repr(PyObject *self) { - Py_ssize_t i, n; - _PyUnicodeWriter writer; - - n = Py_SIZE(v); - if (n == 0) + PyTupleObject *v = _PyTuple_CAST(self); + Py_ssize_t n = PyTuple_GET_SIZE(v); + if (n == 0) { return PyUnicode_FromString("()"); + } /* While not mutable, it is still possible to end up with a cycle in a tuple through an object that stores itself within a tuple (and thus infinitely asks for the repr of itself). This should only be possible within a type. */ - i = Py_ReprEnter((PyObject *)v); - if (i != 0) { - return i > 0 ? PyUnicode_FromString("(...)") : NULL; + int res = Py_ReprEnter((PyObject *)v); + if (res != 0) { + return res > 0 ? PyUnicode_FromString("(...)") : NULL; } + _PyUnicodeWriter writer; _PyUnicodeWriter_Init(&writer); writer.overallocate = 1; - if (Py_SIZE(v) > 1) { + if (n > 1) { /* "(" + "1" + ", 2" * (len - 1) + ")" */ - writer.min_length = 1 + 1 + (2 + 1) * (Py_SIZE(v) - 1) + 1; + writer.min_length = 1 + 1 + (2 + 1) * (n - 1) + 1; } else { /* "(1,)" */ @@ -247,7 +248,7 @@ tuplerepr(PyTupleObject *v) goto error; /* Do repr() on each element. */ - for (i = 0; i < n; ++i) { + for (Py_ssize_t i = 0; i < n; ++i) { PyObject *s; if (i > 0) { @@ -316,13 +317,14 @@ tuplerepr(PyTupleObject *v) /* Tests have shown that it's not worth to cache the hash value, see https://bugs.python.org/issue9685 */ static Py_hash_t -tuplehash(PyTupleObject *v) +tuple_hash(PyObject *op) { - Py_ssize_t i, len = Py_SIZE(v); + PyTupleObject *v = _PyTuple_CAST(op); + Py_ssize_t len = Py_SIZE(v); PyObject **item = v->ob_item; Py_uhash_t acc = _PyHASH_XXPRIME_5; - for (i = 0; i < len; i++) { + for (Py_ssize_t i = 0; i < len; i++) { Py_uhash_t lane = PyObject_Hash(item[i]); if (lane == (Py_uhash_t)-1) { return -1; @@ -342,25 +344,27 @@ tuplehash(PyTupleObject *v) } static Py_ssize_t -tuplelength(PyTupleObject *a) +tuple_length(PyObject *self) { + PyTupleObject *a = _PyTuple_CAST(self); return Py_SIZE(a); } static int -tuplecontains(PyTupleObject *a, PyObject *el) +tuple_contains(PyObject *self, PyObject *el) { - Py_ssize_t i; - int cmp; - - for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i) + PyTupleObject *a = _PyTuple_CAST(self); + int cmp = 0; + for (Py_ssize_t i = 0; cmp == 0 && i < Py_SIZE(a); ++i) { cmp = PyObject_RichCompareBool(PyTuple_GET_ITEM(a, i), el, Py_EQ); + } return cmp; } static PyObject * -tupleitem(PyTupleObject *a, Py_ssize_t i) +tuple_item(PyObject *op, Py_ssize_t i) { + PyTupleObject *a = _PyTuple_CAST(op); if (i < 0 || i >= Py_SIZE(a)) { PyErr_SetString(PyExc_IndexError, "tuple index out of range"); return NULL; @@ -432,7 +436,7 @@ _PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n) } static PyObject * -tupleslice(PyTupleObject *a, Py_ssize_t ilow, +tuple_slice(PyTupleObject *a, Py_ssize_t ilow, Py_ssize_t ihigh) { if (ilow < 0) @@ -454,16 +458,13 @@ PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j) PyErr_BadInternalCall(); return NULL; } - return tupleslice((PyTupleObject *)op, i, j); + return tuple_slice((PyTupleObject *)op, i, j); } static PyObject * -tupleconcat(PyTupleObject *a, PyObject *bb) +tuple_concat(PyObject *aa, PyObject *bb) { - Py_ssize_t size; - Py_ssize_t i; - PyObject **src, **dest; - PyTupleObject *np; + PyTupleObject *a = _PyTuple_CAST(aa); if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) { return Py_NewRef(bb); } @@ -479,34 +480,38 @@ tupleconcat(PyTupleObject *a, PyObject *bb) return Py_NewRef(a); } assert((size_t)Py_SIZE(a) + (size_t)Py_SIZE(b) < PY_SSIZE_T_MAX); - size = Py_SIZE(a) + Py_SIZE(b); + Py_ssize_t size = Py_SIZE(a) + Py_SIZE(b); if (size == 0) { return tuple_get_empty(); } - np = tuple_alloc(size); + PyTupleObject *np = tuple_alloc(size); if (np == NULL) { return NULL; } - src = a->ob_item; - dest = np->ob_item; - for (i = 0; i < Py_SIZE(a); i++) { + + PyObject **src = a->ob_item; + PyObject **dest = np->ob_item; + for (Py_ssize_t i = 0; i < Py_SIZE(a); i++) { PyObject *v = src[i]; dest[i] = Py_NewRef(v); } + src = b->ob_item; dest = np->ob_item + Py_SIZE(a); - for (i = 0; i < Py_SIZE(b); i++) { + for (Py_ssize_t i = 0; i < Py_SIZE(b); i++) { PyObject *v = src[i]; dest[i] = Py_NewRef(v); } + _PyObject_GC_TRACK(np); return (PyObject *)np; } static PyObject * -tuplerepeat(PyTupleObject *a, Py_ssize_t n) +tuple_repeat(PyObject *self, Py_ssize_t n) { + PyTupleObject *a = _PyTuple_CAST(self); const Py_ssize_t input_size = Py_SIZE(a); if (input_size == 0 || n == 1) { if (PyTuple_CheckExact(a)) { @@ -621,17 +626,17 @@ tuple_count(PyTupleObject *self, PyObject *value) } static int -tupletraverse(PyTupleObject *o, visitproc visit, void *arg) +tuple_traverse(PyObject *self, visitproc visit, void *arg) { - Py_ssize_t i; - - for (i = Py_SIZE(o); --i >= 0; ) + PyTupleObject *o = _PyTuple_CAST(self); + for (Py_ssize_t i = Py_SIZE(o); --i >= 0; ) { Py_VISIT(o->ob_item[i]); + } return 0; } static PyObject * -tuplerichcompare(PyObject *v, PyObject *w, int op) +tuple_richcompare(PyObject *v, PyObject *w, int op) { PyTupleObject *vt, *wt; Py_ssize_t i; @@ -770,26 +775,27 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable) } static PySequenceMethods tuple_as_sequence = { - (lenfunc)tuplelength, /* sq_length */ - (binaryfunc)tupleconcat, /* sq_concat */ - (ssizeargfunc)tuplerepeat, /* sq_repeat */ - (ssizeargfunc)tupleitem, /* sq_item */ + tuple_length, /* sq_length */ + tuple_concat, /* sq_concat */ + tuple_repeat, /* sq_repeat */ + tuple_item, /* sq_item */ 0, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ - (objobjproc)tuplecontains, /* sq_contains */ + tuple_contains, /* sq_contains */ }; static PyObject* -tuplesubscript(PyTupleObject* self, PyObject* item) +tuple_subscript(PyObject *op, PyObject* item) { + PyTupleObject *self = _PyTuple_CAST(op); if (_PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; if (i < 0) i += PyTuple_GET_SIZE(self); - return tupleitem(self, i); + return tuple_item(op, i); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, i; @@ -843,7 +849,7 @@ static PyObject * tuple___getnewargs___impl(PyTupleObject *self) /*[clinic end generated code: output=25e06e3ee56027e2 input=1aeb4b286a21639a]*/ { - return Py_BuildValue("(N)", tupleslice(self, 0, Py_SIZE(self))); + return Py_BuildValue("(N)", tuple_slice(self, 0, Py_SIZE(self))); } static PyMethodDef tuple_methods[] = { @@ -855,8 +861,8 @@ static PyMethodDef tuple_methods[] = { }; static PyMappingMethods tuple_as_mapping = { - (lenfunc)tuplelength, - (binaryfunc)tuplesubscript, + tuple_length, + tuple_subscript, 0 }; @@ -867,16 +873,16 @@ PyTypeObject PyTuple_Type = { "tuple", sizeof(PyTupleObject) - sizeof(PyObject *), sizeof(PyObject *), - (destructor)tupledealloc, /* tp_dealloc */ + tuple_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_as_async */ - (reprfunc)tuplerepr, /* tp_repr */ + tuple_repr, /* tp_repr */ 0, /* tp_as_number */ &tuple_as_sequence, /* tp_as_sequence */ &tuple_as_mapping, /* tp_as_mapping */ - (hashfunc)tuplehash, /* tp_hash */ + tuple_hash, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ @@ -886,9 +892,9 @@ PyTypeObject PyTuple_Type = { Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS | _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_SEQUENCE, /* tp_flags */ tuple_new__doc__, /* tp_doc */ - (traverseproc)tupletraverse, /* tp_traverse */ + tuple_traverse, /* tp_traverse */ 0, /* tp_clear */ - tuplerichcompare, /* tp_richcompare */ + tuple_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ tuple_iter, /* tp_iter */ 0, /* tp_iternext */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0e2d9758a5ffae..6484e8921f8122 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3932,7 +3932,7 @@ type_new_alloc(type_new_ctx *ctx) et->ht_token = NULL; #ifdef Py_GIL_DISABLED - _PyType_AssignId(et); + et->unique_id = _PyObject_AssignUniqueId((PyObject *)et); #endif return type; @@ -5026,7 +5026,7 @@ PyType_FromMetaclass( #ifdef Py_GIL_DISABLED // Assign a type id to enable thread-local refcounting - _PyType_AssignId(res); + res->unique_id = _PyObject_AssignUniqueId((PyObject *)res); #endif /* Ready the type (which includes inheritance). @@ -6080,7 +6080,7 @@ type_dealloc(PyObject *self) Py_XDECREF(et->ht_module); PyMem_Free(et->_ht_tpname); #ifdef Py_GIL_DISABLED - _PyType_ReleaseId(et); + _PyObject_ReleaseUniqueId(et->unique_id); #endif et->ht_token = NULL; Py_TYPE(type)->tp_free((PyObject *)type); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 0f502ccdaf5767..60d4875d3b393e 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -282,37 +282,13 @@ hashtable_unicode_compare(const void *key1, const void *key2) } } -/* Return true if this interpreter should share the main interpreter's - intern_dict. That's important for interpreters which load basic - single-phase init extension modules (m_size == -1). There could be interned - immortal strings that are shared between interpreters, due to the - PyDict_Update(mdict, m_copy) call in import_find_extension(). - - It's not safe to deallocate those strings until all interpreters that - potentially use them are freed. By storing them in the main interpreter, we - ensure they get freed after all other interpreters are freed. -*/ -static bool -has_shared_intern_dict(PyInterpreterState *interp) -{ - PyInterpreterState *main_interp = _PyInterpreterState_Main(); - return interp != main_interp && interp->feature_flags & Py_RTFLAGS_USE_MAIN_OBMALLOC; -} - static int init_interned_dict(PyInterpreterState *interp) { assert(get_interned_dict(interp) == NULL); - PyObject *interned; - if (has_shared_intern_dict(interp)) { - interned = get_interned_dict(_PyInterpreterState_Main()); - Py_INCREF(interned); - } - else { - interned = PyDict_New(); - if (interned == NULL) { - return -1; - } + PyObject *interned = interned = PyDict_New(); + if (interned == NULL) { + return -1; } _Py_INTERP_CACHED_OBJECT(interp, interned_strings) = interned; return 0; @@ -323,10 +299,7 @@ clear_interned_dict(PyInterpreterState *interp) { PyObject *interned = get_interned_dict(interp); if (interned != NULL) { - if (!has_shared_intern_dict(interp)) { - // only clear if the dict belongs to this interpreter - PyDict_Clear(interned); - } + PyDict_Clear(interned); Py_DECREF(interned); _Py_INTERP_CACHED_OBJECT(interp, interned_strings) = NULL; } @@ -11028,6 +11001,24 @@ _PyUnicode_Equal(PyObject *str1, PyObject *str2) } +int +PyUnicode_Equal(PyObject *str1, PyObject *str2) +{ + if (!PyUnicode_Check(str1)) { + PyErr_Format(PyExc_TypeError, + "first argument must be str, not %T", str1); + return -1; + } + if (!PyUnicode_Check(str2)) { + PyErr_Format(PyExc_TypeError, + "second argument must be str, not %T", str2); + return -1; + } + + return _PyUnicode_Equal(str1, str2); +} + + int PyUnicode_Compare(PyObject *left, PyObject *right) { @@ -15645,13 +15636,6 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp) } assert(PyDict_CheckExact(interned)); - if (has_shared_intern_dict(interp)) { - // the dict doesn't belong to this interpreter, skip the debug - // checks on it and just clear the pointer to it - clear_interned_dict(interp); - return; - } - #ifdef INTERNED_STATS fprintf(stderr, "releasing %zd interned strings\n", PyDict_GET_SIZE(interned)); @@ -16160,10 +16144,8 @@ _PyUnicode_Fini(PyInterpreterState *interp) { struct _Py_unicode_state *state = &interp->unicode; - if (!has_shared_intern_dict(interp)) { - // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini() - assert(get_interned_dict(interp) == NULL); - } + // _PyUnicode_ClearInterned() must be called before _PyUnicode_Fini() + assert(get_interned_dict(interp) == NULL); _PyUnicode_FiniEncodings(&state->fs_codec); diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index 61f05514a48023..9e3da1c3394d5b 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -104,9 +104,11 @@ clear_weakref_lock_held(PyWeakReference *self, PyObject **callback) // Clear the weakref and its callback static void -clear_weakref(PyWeakReference *self) +clear_weakref(PyObject *op) { + PyWeakReference *self = _PyWeakref_CAST(op); PyObject *callback = NULL; + // self->wr_object may be Py_None if the GC cleared the weakref, so lock // using the pointer in the weakref. LOCK_WEAKREFS_FOR_WR(self); @@ -139,22 +141,24 @@ static void weakref_dealloc(PyObject *self) { PyObject_GC_UnTrack(self); - clear_weakref((PyWeakReference *) self); + clear_weakref(self); Py_TYPE(self)->tp_free(self); } static int -gc_traverse(PyWeakReference *self, visitproc visit, void *arg) +gc_traverse(PyObject *op, visitproc visit, void *arg) { + PyWeakReference *self = _PyWeakref_CAST(op); Py_VISIT(self->wr_callback); return 0; } static int -gc_clear(PyWeakReference *self) +gc_clear(PyObject *op) { + PyWeakReference *self = _PyWeakref_CAST(op); PyObject *callback; // The world is stopped during GC in free-threaded builds. It's safe to // call this without holding the lock. @@ -198,8 +202,9 @@ weakref_hash_lock_held(PyWeakReference *self) } static Py_hash_t -weakref_hash(PyWeakReference *self) +weakref_hash(PyObject *op) { + PyWeakReference *self = _PyWeakref_CAST(op); Py_hash_t hash; Py_BEGIN_CRITICAL_SECTION(self); hash = weakref_hash_lock_held(self); @@ -499,11 +504,11 @@ _PyWeakref_RefType = { .tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall), .tp_call = PyVectorcall_Call, .tp_repr = weakref_repr, - .tp_hash = (hashfunc)weakref_hash, + .tp_hash = weakref_hash, .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_BASETYPE, - .tp_traverse = (traverseproc)gc_traverse, - .tp_clear = (inquiry)gc_clear, + .tp_traverse = gc_traverse, + .tp_clear = gc_clear, .tp_richcompare = weakref_richcompare, .tp_methods = weakref_methods, .tp_members = weakref_members, @@ -687,7 +692,7 @@ proxy_bool(PyObject *proxy) } static void -proxy_dealloc(PyWeakReference *self) +proxy_dealloc(PyObject *self) { PyObject_GC_UnTrack(self); clear_weakref(self); @@ -850,7 +855,7 @@ _PyWeakref_ProxyType = { sizeof(PyWeakReference), 0, /* methods */ - (destructor)proxy_dealloc, /* tp_dealloc */ + proxy_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -868,8 +873,8 @@ _PyWeakref_ProxyType = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)gc_traverse, /* tp_traverse */ - (inquiry)gc_clear, /* tp_clear */ + gc_traverse, /* tp_traverse */ + gc_clear, /* tp_clear */ proxy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ proxy_iter, /* tp_iter */ @@ -885,7 +890,7 @@ _PyWeakref_CallableProxyType = { sizeof(PyWeakReference), 0, /* methods */ - (destructor)proxy_dealloc, /* tp_dealloc */ + proxy_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -902,8 +907,8 @@ _PyWeakref_CallableProxyType = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ 0, /* tp_doc */ - (traverseproc)gc_traverse, /* tp_traverse */ - (inquiry)gc_clear, /* tp_clear */ + gc_traverse, /* tp_traverse */ + gc_clear, /* tp_clear */ proxy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ proxy_iter, /* tp_iter */ diff --git a/PC/python3dll.c b/PC/python3dll.c index 6b8208ab90bd95..9296474617e115 100755 --- a/PC/python3dll.c +++ b/PC/python3dll.c @@ -717,6 +717,7 @@ EXPORT_FUNC(PyUnicode_DecodeUTF8Stateful) EXPORT_FUNC(PyUnicode_EncodeCodePage) EXPORT_FUNC(PyUnicode_EncodeFSDefault) EXPORT_FUNC(PyUnicode_EncodeLocale) +EXPORT_FUNC(PyUnicode_Equal) EXPORT_FUNC(PyUnicode_EqualToUTF8) EXPORT_FUNC(PyUnicode_EqualToUTF8AndSize) EXPORT_FUNC(PyUnicode_Find) diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj index 743e6e2a66a8f1..a3c2d32c454e04 100644 --- a/PCbuild/_freeze_module.vcxproj +++ b/PCbuild/_freeze_module.vcxproj @@ -268,7 +268,7 @@ - + diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters index 0887a47917a931..91b1d75fb8df5e 100644 --- a/PCbuild/_freeze_module.vcxproj.filters +++ b/PCbuild/_freeze_module.vcxproj.filters @@ -467,7 +467,7 @@ Source Files - + Source Files diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 19b982db7f5b87..3b33c6bf6bb91d 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -304,13 +304,13 @@ - + @@ -657,7 +657,7 @@ - + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 23f2e9c8bc0eb7..ee2930b10439a9 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -831,9 +831,6 @@ Include\internal - - Include\internal - Include\internal @@ -846,6 +843,9 @@ Include\internal + + Include\internal + Include\internal\mimalloc @@ -1499,7 +1499,7 @@ Python - + Python diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index fac9a7740a1fe6..f50c28afcfe205 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -843,8 +843,9 @@ def visitModule(self, mod): } AST_object; static void -ast_dealloc(AST_object *self) +ast_dealloc(PyObject *op) { + AST_object *self = (AST_object*)op; /* bpo-31095: UnTrack is needed before calling any callbacks */ PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); @@ -856,16 +857,18 @@ def visitModule(self, mod): } static int -ast_traverse(AST_object *self, visitproc visit, void *arg) +ast_traverse(PyObject *op, visitproc visit, void *arg) { + AST_object *self = (AST_object*)op; Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; } static int -ast_clear(AST_object *self) +ast_clear(PyObject *op) { + AST_object *self = (AST_object*)op; Py_CLEAR(self->dict); return 0; } @@ -1605,7 +1608,6 @@ def visitModule(self, mod): if (!value_repr) { Py_DECREF(name); - Py_DECREF(value); goto error; } @@ -1651,9 +1653,9 @@ def visitModule(self, mod): } static PyObject * -ast_repr(AST_object *self) +ast_repr(PyObject *self) { - return ast_repr_max_depth(self, 3); + return ast_repr_max_depth((AST_object*)self, 3); } static PyType_Slot AST_type_slots[] = { @@ -1847,8 +1849,9 @@ def visitModule(self, mod): self.file.write(textwrap.dedent(''' static int - init_types(struct ast_state *state) + init_types(void *arg) { + struct ast_state *state = arg; if (init_identifiers(state) < 0) { return -1; } @@ -2296,7 +2299,7 @@ def generate_module_def(mod, metadata, f, internal_h): }; // Forward declaration - static int init_types(struct ast_state *state); + static int init_types(void *arg); static struct ast_state* get_ast_state(void) diff --git a/Parser/parser.c b/Parser/parser.c index e5567d0f63f03b..9ff58ab7e7bfd5 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -338,156 +338,156 @@ static char *soft_keywords[] = { #define invalid_factor_type 1251 #define invalid_type_params_type 1252 #define _loop0_1_type 1253 -#define _loop0_2_type 1254 -#define _loop1_3_type 1255 -#define _loop0_5_type 1256 -#define _gather_4_type 1257 +#define _loop1_2_type 1254 +#define _loop0_3_type 1255 +#define _gather_4_type 1256 +#define _tmp_5_type 1257 #define _tmp_6_type 1258 #define _tmp_7_type 1259 #define _tmp_8_type 1260 #define _tmp_9_type 1261 #define _tmp_10_type 1262 #define _tmp_11_type 1263 -#define _tmp_12_type 1264 +#define _loop1_12_type 1264 #define _tmp_13_type 1265 -#define _loop1_14_type 1266 -#define _tmp_15_type 1267 +#define _loop0_14_type 1266 +#define _gather_15_type 1267 #define _tmp_16_type 1268 #define _tmp_17_type 1269 -#define _loop0_19_type 1270 -#define _gather_18_type 1271 -#define _loop0_21_type 1272 -#define _gather_20_type 1273 +#define _loop0_18_type 1270 +#define _loop1_19_type 1271 +#define _loop0_20_type 1272 +#define _gather_21_type 1273 #define _tmp_22_type 1274 -#define _tmp_23_type 1275 -#define _loop0_24_type 1276 +#define _loop0_23_type 1275 +#define _gather_24_type 1276 #define _loop1_25_type 1277 -#define _loop0_27_type 1278 -#define _gather_26_type 1279 -#define _tmp_28_type 1280 -#define _loop0_30_type 1281 -#define _gather_29_type 1282 -#define _tmp_31_type 1283 -#define _loop1_32_type 1284 -#define _tmp_33_type 1285 -#define _tmp_34_type 1286 -#define _tmp_35_type 1287 -#define _loop0_36_type 1288 -#define _loop0_37_type 1289 -#define _loop0_38_type 1290 +#define _tmp_26_type 1278 +#define _tmp_27_type 1279 +#define _loop0_28_type 1280 +#define _loop0_29_type 1281 +#define _loop1_30_type 1282 +#define _loop1_31_type 1283 +#define _loop0_32_type 1284 +#define _loop1_33_type 1285 +#define _loop0_34_type 1286 +#define _gather_35_type 1287 +#define _tmp_36_type 1288 +#define _loop1_37_type 1289 +#define _loop1_38_type 1290 #define _loop1_39_type 1291 #define _loop0_40_type 1292 -#define _loop1_41_type 1293 -#define _loop1_42_type 1294 -#define _loop1_43_type 1295 +#define _gather_41_type 1293 +#define _tmp_42_type 1294 +#define _tmp_43_type 1295 #define _loop0_44_type 1296 -#define _loop1_45_type 1297 +#define _gather_45_type 1297 #define _loop0_46_type 1298 -#define _loop1_47_type 1299 -#define _loop0_48_type 1300 +#define _gather_47_type 1299 +#define _tmp_48_type 1300 #define _loop0_49_type 1301 -#define _loop1_50_type 1302 -#define _loop0_52_type 1303 -#define _gather_51_type 1304 -#define _loop0_54_type 1305 -#define _gather_53_type 1306 -#define _loop0_56_type 1307 -#define _gather_55_type 1308 -#define _loop0_58_type 1309 -#define _gather_57_type 1310 -#define _tmp_59_type 1311 +#define _gather_50_type 1302 +#define _loop0_51_type 1303 +#define _gather_52_type 1304 +#define _loop0_53_type 1305 +#define _gather_54_type 1306 +#define _loop1_55_type 1307 +#define _loop1_56_type 1308 +#define _loop0_57_type 1309 +#define _gather_58_type 1310 +#define _loop1_59_type 1311 #define _loop1_60_type 1312 #define _loop1_61_type 1313 #define _tmp_62_type 1314 -#define _tmp_63_type 1315 -#define _loop1_64_type 1316 -#define _loop0_66_type 1317 -#define _gather_65_type 1318 +#define _loop0_63_type 1315 +#define _gather_64_type 1316 +#define _tmp_65_type 1317 +#define _tmp_66_type 1318 #define _tmp_67_type 1319 #define _tmp_68_type 1320 #define _tmp_69_type 1321 #define _tmp_70_type 1322 -#define _loop0_72_type 1323 -#define _gather_71_type 1324 -#define _loop0_74_type 1325 -#define _gather_73_type 1326 -#define _tmp_75_type 1327 -#define _loop0_77_type 1328 -#define _gather_76_type 1329 -#define _loop0_79_type 1330 -#define _gather_78_type 1331 -#define _loop0_81_type 1332 -#define _gather_80_type 1333 -#define _loop1_82_type 1334 +#define _loop0_71_type 1323 +#define _loop0_72_type 1324 +#define _loop1_73_type 1325 +#define _loop1_74_type 1326 +#define _loop0_75_type 1327 +#define _loop1_76_type 1328 +#define _loop0_77_type 1329 +#define _loop0_78_type 1330 +#define _loop1_79_type 1331 +#define _tmp_80_type 1332 +#define _loop0_81_type 1333 +#define _gather_82_type 1334 #define _loop1_83_type 1335 -#define _loop0_85_type 1336 -#define _gather_84_type 1337 -#define _loop1_86_type 1338 -#define _loop1_87_type 1339 -#define _loop1_88_type 1340 -#define _tmp_89_type 1341 -#define _loop0_91_type 1342 -#define _gather_90_type 1343 -#define _tmp_92_type 1344 -#define _tmp_93_type 1345 -#define _tmp_94_type 1346 -#define _tmp_95_type 1347 -#define _tmp_96_type 1348 +#define _loop0_84_type 1336 +#define _tmp_85_type 1337 +#define _loop0_86_type 1338 +#define _gather_87_type 1339 +#define _tmp_88_type 1340 +#define _loop0_89_type 1341 +#define _gather_90_type 1342 +#define _loop0_91_type 1343 +#define _gather_92_type 1344 +#define _loop0_93_type 1345 +#define _loop0_94_type 1346 +#define _gather_95_type 1347 +#define _loop1_96_type 1348 #define _tmp_97_type 1349 #define _loop0_98_type 1350 -#define _loop0_99_type 1351 +#define _gather_99_type 1351 #define _loop0_100_type 1352 -#define _loop1_101_type 1353 -#define _loop0_102_type 1354 -#define _loop1_103_type 1355 -#define _loop1_104_type 1356 -#define _loop1_105_type 1357 -#define _loop0_106_type 1358 -#define _loop1_107_type 1359 -#define _loop0_108_type 1360 -#define _loop1_109_type 1361 -#define _loop0_110_type 1362 -#define _loop1_111_type 1363 -#define _loop0_112_type 1364 -#define _loop0_113_type 1365 -#define _loop1_114_type 1366 -#define _tmp_115_type 1367 -#define _loop0_117_type 1368 -#define _gather_116_type 1369 -#define _loop1_118_type 1370 -#define _loop0_119_type 1371 -#define _loop0_120_type 1372 +#define _gather_101_type 1353 +#define _tmp_102_type 1354 +#define _tmp_103_type 1355 +#define _loop0_104_type 1356 +#define _gather_105_type 1357 +#define _tmp_106_type 1358 +#define _tmp_107_type 1359 +#define _tmp_108_type 1360 +#define _tmp_109_type 1361 +#define _tmp_110_type 1362 +#define _tmp_111_type 1363 +#define _tmp_112_type 1364 +#define _tmp_113_type 1365 +#define _tmp_114_type 1366 +#define _loop0_115_type 1367 +#define _loop0_116_type 1368 +#define _tmp_117_type 1369 +#define _tmp_118_type 1370 +#define _tmp_119_type 1371 +#define _tmp_120_type 1372 #define _tmp_121_type 1373 -#define _loop0_123_type 1374 -#define _gather_122_type 1375 +#define _tmp_122_type 1374 +#define _tmp_123_type 1375 #define _tmp_124_type 1376 -#define _loop0_126_type 1377 -#define _gather_125_type 1378 -#define _loop0_128_type 1379 -#define _gather_127_type 1380 -#define _loop0_130_type 1381 -#define _gather_129_type 1382 -#define _loop0_132_type 1383 -#define _gather_131_type 1384 -#define _loop0_133_type 1385 -#define _loop0_135_type 1386 -#define _gather_134_type 1387 -#define _loop1_136_type 1388 -#define _tmp_137_type 1389 -#define _loop0_139_type 1390 -#define _gather_138_type 1391 -#define _loop0_141_type 1392 -#define _gather_140_type 1393 -#define _loop0_143_type 1394 -#define _gather_142_type 1395 -#define _loop0_145_type 1396 -#define _gather_144_type 1397 -#define _loop0_147_type 1398 -#define _gather_146_type 1399 +#define _tmp_125_type 1377 +#define _loop0_126_type 1378 +#define _gather_127_type 1379 +#define _tmp_128_type 1380 +#define _tmp_129_type 1381 +#define _tmp_130_type 1382 +#define _tmp_131_type 1383 +#define _loop0_132_type 1384 +#define _gather_133_type 1385 +#define _loop0_134_type 1386 +#define _gather_135_type 1387 +#define _loop0_136_type 1388 +#define _gather_137_type 1389 +#define _tmp_138_type 1390 +#define _loop0_139_type 1391 +#define _tmp_140_type 1392 +#define _tmp_141_type 1393 +#define _tmp_142_type 1394 +#define _tmp_143_type 1395 +#define _tmp_144_type 1396 +#define _tmp_145_type 1397 +#define _tmp_146_type 1398 +#define _tmp_147_type 1399 #define _tmp_148_type 1400 #define _tmp_149_type 1401 -#define _loop0_151_type 1402 -#define _gather_150_type 1403 +#define _tmp_150_type 1402 +#define _tmp_151_type 1403 #define _tmp_152_type 1404 #define _tmp_153_type 1405 #define _tmp_154_type 1406 @@ -498,128 +498,14 @@ static char *soft_keywords[] = { #define _tmp_159_type 1411 #define _tmp_160_type 1412 #define _tmp_161_type 1413 -#define _loop0_162_type 1414 -#define _loop0_163_type 1415 -#define _loop0_164_type 1416 -#define _tmp_165_type 1417 +#define _tmp_162_type 1414 +#define _tmp_163_type 1415 +#define _tmp_164_type 1416 +#define _loop0_165_type 1417 #define _tmp_166_type 1418 #define _tmp_167_type 1419 #define _tmp_168_type 1420 -#define _loop0_169_type 1421 -#define _loop0_170_type 1422 -#define _loop0_171_type 1423 -#define _loop1_172_type 1424 -#define _tmp_173_type 1425 -#define _loop0_174_type 1426 -#define _tmp_175_type 1427 -#define _loop0_176_type 1428 -#define _loop1_177_type 1429 -#define _tmp_178_type 1430 -#define _tmp_179_type 1431 -#define _tmp_180_type 1432 -#define _loop0_181_type 1433 -#define _tmp_182_type 1434 -#define _tmp_183_type 1435 -#define _loop1_184_type 1436 -#define _tmp_185_type 1437 -#define _loop0_186_type 1438 -#define _loop0_187_type 1439 -#define _loop0_188_type 1440 -#define _loop0_190_type 1441 -#define _gather_189_type 1442 -#define _tmp_191_type 1443 -#define _loop0_192_type 1444 -#define _tmp_193_type 1445 -#define _loop0_194_type 1446 -#define _loop1_195_type 1447 -#define _loop1_196_type 1448 -#define _tmp_197_type 1449 -#define _tmp_198_type 1450 -#define _loop0_199_type 1451 -#define _tmp_200_type 1452 -#define _tmp_201_type 1453 -#define _tmp_202_type 1454 -#define _tmp_203_type 1455 -#define _loop0_205_type 1456 -#define _gather_204_type 1457 -#define _loop0_207_type 1458 -#define _gather_206_type 1459 -#define _loop0_209_type 1460 -#define _gather_208_type 1461 -#define _loop0_211_type 1462 -#define _gather_210_type 1463 -#define _loop0_213_type 1464 -#define _gather_212_type 1465 -#define _tmp_214_type 1466 -#define _loop0_215_type 1467 -#define _loop1_216_type 1468 -#define _tmp_217_type 1469 -#define _loop0_218_type 1470 -#define _loop1_219_type 1471 -#define _tmp_220_type 1472 -#define _tmp_221_type 1473 -#define _tmp_222_type 1474 -#define _tmp_223_type 1475 -#define _tmp_224_type 1476 -#define _tmp_225_type 1477 -#define _tmp_226_type 1478 -#define _tmp_227_type 1479 -#define _tmp_228_type 1480 -#define _tmp_229_type 1481 -#define _tmp_230_type 1482 -#define _tmp_231_type 1483 -#define _tmp_232_type 1484 -#define _loop0_234_type 1485 -#define _gather_233_type 1486 -#define _tmp_235_type 1487 -#define _tmp_236_type 1488 -#define _tmp_237_type 1489 -#define _tmp_238_type 1490 -#define _tmp_239_type 1491 -#define _tmp_240_type 1492 -#define _tmp_241_type 1493 -#define _loop0_242_type 1494 -#define _tmp_243_type 1495 -#define _tmp_244_type 1496 -#define _tmp_245_type 1497 -#define _tmp_246_type 1498 -#define _tmp_247_type 1499 -#define _tmp_248_type 1500 -#define _tmp_249_type 1501 -#define _tmp_250_type 1502 -#define _tmp_251_type 1503 -#define _tmp_252_type 1504 -#define _tmp_253_type 1505 -#define _tmp_254_type 1506 -#define _tmp_255_type 1507 -#define _tmp_256_type 1508 -#define _tmp_257_type 1509 -#define _tmp_258_type 1510 -#define _tmp_259_type 1511 -#define _tmp_260_type 1512 -#define _tmp_261_type 1513 -#define _tmp_262_type 1514 -#define _tmp_263_type 1515 -#define _tmp_264_type 1516 -#define _tmp_265_type 1517 -#define _tmp_266_type 1518 -#define _tmp_267_type 1519 -#define _loop0_268_type 1520 -#define _tmp_269_type 1521 -#define _tmp_270_type 1522 -#define _tmp_271_type 1523 -#define _tmp_272_type 1524 -#define _tmp_273_type 1525 -#define _tmp_274_type 1526 -#define _loop0_276_type 1527 -#define _gather_275_type 1528 -#define _tmp_277_type 1529 -#define _tmp_278_type 1530 -#define _tmp_279_type 1531 -#define _tmp_280_type 1532 -#define _tmp_281_type 1533 -#define _tmp_282_type 1534 -#define _tmp_283_type 1535 +#define _tmp_169_type 1421 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -875,156 +761,156 @@ static void *invalid_arithmetic_rule(Parser *p); static void *invalid_factor_rule(Parser *p); static void *invalid_type_params_rule(Parser *p); static asdl_seq *_loop0_1_rule(Parser *p); -static asdl_seq *_loop0_2_rule(Parser *p); -static asdl_seq *_loop1_3_rule(Parser *p); -static asdl_seq *_loop0_5_rule(Parser *p); +static asdl_seq *_loop1_2_rule(Parser *p); +static asdl_seq *_loop0_3_rule(Parser *p); static asdl_seq *_gather_4_rule(Parser *p); +static void *_tmp_5_rule(Parser *p); static void *_tmp_6_rule(Parser *p); static void *_tmp_7_rule(Parser *p); static void *_tmp_8_rule(Parser *p); static void *_tmp_9_rule(Parser *p); static void *_tmp_10_rule(Parser *p); static void *_tmp_11_rule(Parser *p); -static void *_tmp_12_rule(Parser *p); +static asdl_seq *_loop1_12_rule(Parser *p); static void *_tmp_13_rule(Parser *p); -static asdl_seq *_loop1_14_rule(Parser *p); -static void *_tmp_15_rule(Parser *p); +static asdl_seq *_loop0_14_rule(Parser *p); +static asdl_seq *_gather_15_rule(Parser *p); static void *_tmp_16_rule(Parser *p); static void *_tmp_17_rule(Parser *p); -static asdl_seq *_loop0_19_rule(Parser *p); -static asdl_seq *_gather_18_rule(Parser *p); -static asdl_seq *_loop0_21_rule(Parser *p); -static asdl_seq *_gather_20_rule(Parser *p); +static asdl_seq *_loop0_18_rule(Parser *p); +static asdl_seq *_loop1_19_rule(Parser *p); +static asdl_seq *_loop0_20_rule(Parser *p); +static asdl_seq *_gather_21_rule(Parser *p); static void *_tmp_22_rule(Parser *p); -static void *_tmp_23_rule(Parser *p); -static asdl_seq *_loop0_24_rule(Parser *p); +static asdl_seq *_loop0_23_rule(Parser *p); +static asdl_seq *_gather_24_rule(Parser *p); static asdl_seq *_loop1_25_rule(Parser *p); -static asdl_seq *_loop0_27_rule(Parser *p); -static asdl_seq *_gather_26_rule(Parser *p); -static void *_tmp_28_rule(Parser *p); -static asdl_seq *_loop0_30_rule(Parser *p); -static asdl_seq *_gather_29_rule(Parser *p); -static void *_tmp_31_rule(Parser *p); -static asdl_seq *_loop1_32_rule(Parser *p); -static void *_tmp_33_rule(Parser *p); -static void *_tmp_34_rule(Parser *p); -static void *_tmp_35_rule(Parser *p); -static asdl_seq *_loop0_36_rule(Parser *p); -static asdl_seq *_loop0_37_rule(Parser *p); -static asdl_seq *_loop0_38_rule(Parser *p); +static void *_tmp_26_rule(Parser *p); +static void *_tmp_27_rule(Parser *p); +static asdl_seq *_loop0_28_rule(Parser *p); +static asdl_seq *_loop0_29_rule(Parser *p); +static asdl_seq *_loop1_30_rule(Parser *p); +static asdl_seq *_loop1_31_rule(Parser *p); +static asdl_seq *_loop0_32_rule(Parser *p); +static asdl_seq *_loop1_33_rule(Parser *p); +static asdl_seq *_loop0_34_rule(Parser *p); +static asdl_seq *_gather_35_rule(Parser *p); +static void *_tmp_36_rule(Parser *p); +static asdl_seq *_loop1_37_rule(Parser *p); +static asdl_seq *_loop1_38_rule(Parser *p); static asdl_seq *_loop1_39_rule(Parser *p); static asdl_seq *_loop0_40_rule(Parser *p); -static asdl_seq *_loop1_41_rule(Parser *p); -static asdl_seq *_loop1_42_rule(Parser *p); -static asdl_seq *_loop1_43_rule(Parser *p); +static asdl_seq *_gather_41_rule(Parser *p); +static void *_tmp_42_rule(Parser *p); +static void *_tmp_43_rule(Parser *p); static asdl_seq *_loop0_44_rule(Parser *p); -static asdl_seq *_loop1_45_rule(Parser *p); +static asdl_seq *_gather_45_rule(Parser *p); static asdl_seq *_loop0_46_rule(Parser *p); -static asdl_seq *_loop1_47_rule(Parser *p); -static asdl_seq *_loop0_48_rule(Parser *p); +static asdl_seq *_gather_47_rule(Parser *p); +static void *_tmp_48_rule(Parser *p); static asdl_seq *_loop0_49_rule(Parser *p); -static asdl_seq *_loop1_50_rule(Parser *p); -static asdl_seq *_loop0_52_rule(Parser *p); -static asdl_seq *_gather_51_rule(Parser *p); -static asdl_seq *_loop0_54_rule(Parser *p); -static asdl_seq *_gather_53_rule(Parser *p); -static asdl_seq *_loop0_56_rule(Parser *p); -static asdl_seq *_gather_55_rule(Parser *p); -static asdl_seq *_loop0_58_rule(Parser *p); -static asdl_seq *_gather_57_rule(Parser *p); -static void *_tmp_59_rule(Parser *p); +static asdl_seq *_gather_50_rule(Parser *p); +static asdl_seq *_loop0_51_rule(Parser *p); +static asdl_seq *_gather_52_rule(Parser *p); +static asdl_seq *_loop0_53_rule(Parser *p); +static asdl_seq *_gather_54_rule(Parser *p); +static asdl_seq *_loop1_55_rule(Parser *p); +static asdl_seq *_loop1_56_rule(Parser *p); +static asdl_seq *_loop0_57_rule(Parser *p); +static asdl_seq *_gather_58_rule(Parser *p); +static asdl_seq *_loop1_59_rule(Parser *p); static asdl_seq *_loop1_60_rule(Parser *p); static asdl_seq *_loop1_61_rule(Parser *p); static void *_tmp_62_rule(Parser *p); -static void *_tmp_63_rule(Parser *p); -static asdl_seq *_loop1_64_rule(Parser *p); -static asdl_seq *_loop0_66_rule(Parser *p); -static asdl_seq *_gather_65_rule(Parser *p); +static asdl_seq *_loop0_63_rule(Parser *p); +static asdl_seq *_gather_64_rule(Parser *p); +static void *_tmp_65_rule(Parser *p); +static void *_tmp_66_rule(Parser *p); static void *_tmp_67_rule(Parser *p); static void *_tmp_68_rule(Parser *p); static void *_tmp_69_rule(Parser *p); static void *_tmp_70_rule(Parser *p); +static asdl_seq *_loop0_71_rule(Parser *p); static asdl_seq *_loop0_72_rule(Parser *p); -static asdl_seq *_gather_71_rule(Parser *p); -static asdl_seq *_loop0_74_rule(Parser *p); -static asdl_seq *_gather_73_rule(Parser *p); -static void *_tmp_75_rule(Parser *p); +static asdl_seq *_loop1_73_rule(Parser *p); +static asdl_seq *_loop1_74_rule(Parser *p); +static asdl_seq *_loop0_75_rule(Parser *p); +static asdl_seq *_loop1_76_rule(Parser *p); static asdl_seq *_loop0_77_rule(Parser *p); -static asdl_seq *_gather_76_rule(Parser *p); -static asdl_seq *_loop0_79_rule(Parser *p); -static asdl_seq *_gather_78_rule(Parser *p); +static asdl_seq *_loop0_78_rule(Parser *p); +static asdl_seq *_loop1_79_rule(Parser *p); +static void *_tmp_80_rule(Parser *p); static asdl_seq *_loop0_81_rule(Parser *p); -static asdl_seq *_gather_80_rule(Parser *p); -static asdl_seq *_loop1_82_rule(Parser *p); +static asdl_seq *_gather_82_rule(Parser *p); static asdl_seq *_loop1_83_rule(Parser *p); -static asdl_seq *_loop0_85_rule(Parser *p); -static asdl_seq *_gather_84_rule(Parser *p); -static asdl_seq *_loop1_86_rule(Parser *p); -static asdl_seq *_loop1_87_rule(Parser *p); -static asdl_seq *_loop1_88_rule(Parser *p); -static void *_tmp_89_rule(Parser *p); -static asdl_seq *_loop0_91_rule(Parser *p); +static asdl_seq *_loop0_84_rule(Parser *p); +static void *_tmp_85_rule(Parser *p); +static asdl_seq *_loop0_86_rule(Parser *p); +static asdl_seq *_gather_87_rule(Parser *p); +static void *_tmp_88_rule(Parser *p); +static asdl_seq *_loop0_89_rule(Parser *p); static asdl_seq *_gather_90_rule(Parser *p); -static void *_tmp_92_rule(Parser *p); -static void *_tmp_93_rule(Parser *p); -static void *_tmp_94_rule(Parser *p); -static void *_tmp_95_rule(Parser *p); -static void *_tmp_96_rule(Parser *p); +static asdl_seq *_loop0_91_rule(Parser *p); +static asdl_seq *_gather_92_rule(Parser *p); +static asdl_seq *_loop0_93_rule(Parser *p); +static asdl_seq *_loop0_94_rule(Parser *p); +static asdl_seq *_gather_95_rule(Parser *p); +static asdl_seq *_loop1_96_rule(Parser *p); static void *_tmp_97_rule(Parser *p); static asdl_seq *_loop0_98_rule(Parser *p); -static asdl_seq *_loop0_99_rule(Parser *p); +static asdl_seq *_gather_99_rule(Parser *p); static asdl_seq *_loop0_100_rule(Parser *p); -static asdl_seq *_loop1_101_rule(Parser *p); -static asdl_seq *_loop0_102_rule(Parser *p); -static asdl_seq *_loop1_103_rule(Parser *p); -static asdl_seq *_loop1_104_rule(Parser *p); -static asdl_seq *_loop1_105_rule(Parser *p); -static asdl_seq *_loop0_106_rule(Parser *p); -static asdl_seq *_loop1_107_rule(Parser *p); -static asdl_seq *_loop0_108_rule(Parser *p); -static asdl_seq *_loop1_109_rule(Parser *p); -static asdl_seq *_loop0_110_rule(Parser *p); -static asdl_seq *_loop1_111_rule(Parser *p); -static asdl_seq *_loop0_112_rule(Parser *p); -static asdl_seq *_loop0_113_rule(Parser *p); -static asdl_seq *_loop1_114_rule(Parser *p); -static void *_tmp_115_rule(Parser *p); -static asdl_seq *_loop0_117_rule(Parser *p); -static asdl_seq *_gather_116_rule(Parser *p); -static asdl_seq *_loop1_118_rule(Parser *p); -static asdl_seq *_loop0_119_rule(Parser *p); -static asdl_seq *_loop0_120_rule(Parser *p); +static asdl_seq *_gather_101_rule(Parser *p); +static void *_tmp_102_rule(Parser *p); +static void *_tmp_103_rule(Parser *p); +static asdl_seq *_loop0_104_rule(Parser *p); +static asdl_seq *_gather_105_rule(Parser *p); +static void *_tmp_106_rule(Parser *p); +static void *_tmp_107_rule(Parser *p); +static void *_tmp_108_rule(Parser *p); +static void *_tmp_109_rule(Parser *p); +static void *_tmp_110_rule(Parser *p); +static void *_tmp_111_rule(Parser *p); +static void *_tmp_112_rule(Parser *p); +static void *_tmp_113_rule(Parser *p); +static void *_tmp_114_rule(Parser *p); +static asdl_seq *_loop0_115_rule(Parser *p); +static asdl_seq *_loop0_116_rule(Parser *p); +static void *_tmp_117_rule(Parser *p); +static void *_tmp_118_rule(Parser *p); +static void *_tmp_119_rule(Parser *p); +static void *_tmp_120_rule(Parser *p); static void *_tmp_121_rule(Parser *p); -static asdl_seq *_loop0_123_rule(Parser *p); -static asdl_seq *_gather_122_rule(Parser *p); +static void *_tmp_122_rule(Parser *p); +static void *_tmp_123_rule(Parser *p); static void *_tmp_124_rule(Parser *p); +static void *_tmp_125_rule(Parser *p); static asdl_seq *_loop0_126_rule(Parser *p); -static asdl_seq *_gather_125_rule(Parser *p); -static asdl_seq *_loop0_128_rule(Parser *p); static asdl_seq *_gather_127_rule(Parser *p); -static asdl_seq *_loop0_130_rule(Parser *p); -static asdl_seq *_gather_129_rule(Parser *p); +static void *_tmp_128_rule(Parser *p); +static void *_tmp_129_rule(Parser *p); +static void *_tmp_130_rule(Parser *p); +static void *_tmp_131_rule(Parser *p); static asdl_seq *_loop0_132_rule(Parser *p); -static asdl_seq *_gather_131_rule(Parser *p); -static asdl_seq *_loop0_133_rule(Parser *p); -static asdl_seq *_loop0_135_rule(Parser *p); -static asdl_seq *_gather_134_rule(Parser *p); -static asdl_seq *_loop1_136_rule(Parser *p); -static void *_tmp_137_rule(Parser *p); +static asdl_seq *_gather_133_rule(Parser *p); +static asdl_seq *_loop0_134_rule(Parser *p); +static asdl_seq *_gather_135_rule(Parser *p); +static asdl_seq *_loop0_136_rule(Parser *p); +static asdl_seq *_gather_137_rule(Parser *p); +static void *_tmp_138_rule(Parser *p); static asdl_seq *_loop0_139_rule(Parser *p); -static asdl_seq *_gather_138_rule(Parser *p); -static asdl_seq *_loop0_141_rule(Parser *p); -static asdl_seq *_gather_140_rule(Parser *p); -static asdl_seq *_loop0_143_rule(Parser *p); -static asdl_seq *_gather_142_rule(Parser *p); -static asdl_seq *_loop0_145_rule(Parser *p); -static asdl_seq *_gather_144_rule(Parser *p); -static asdl_seq *_loop0_147_rule(Parser *p); -static asdl_seq *_gather_146_rule(Parser *p); +static void *_tmp_140_rule(Parser *p); +static void *_tmp_141_rule(Parser *p); +static void *_tmp_142_rule(Parser *p); +static void *_tmp_143_rule(Parser *p); +static void *_tmp_144_rule(Parser *p); +static void *_tmp_145_rule(Parser *p); +static void *_tmp_146_rule(Parser *p); +static void *_tmp_147_rule(Parser *p); static void *_tmp_148_rule(Parser *p); static void *_tmp_149_rule(Parser *p); -static asdl_seq *_loop0_151_rule(Parser *p); -static asdl_seq *_gather_150_rule(Parser *p); +static void *_tmp_150_rule(Parser *p); +static void *_tmp_151_rule(Parser *p); static void *_tmp_152_rule(Parser *p); static void *_tmp_153_rule(Parser *p); static void *_tmp_154_rule(Parser *p); @@ -1035,128 +921,14 @@ static void *_tmp_158_rule(Parser *p); static void *_tmp_159_rule(Parser *p); static void *_tmp_160_rule(Parser *p); static void *_tmp_161_rule(Parser *p); -static asdl_seq *_loop0_162_rule(Parser *p); -static asdl_seq *_loop0_163_rule(Parser *p); -static asdl_seq *_loop0_164_rule(Parser *p); -static void *_tmp_165_rule(Parser *p); +static void *_tmp_162_rule(Parser *p); +static void *_tmp_163_rule(Parser *p); +static void *_tmp_164_rule(Parser *p); +static asdl_seq *_loop0_165_rule(Parser *p); static void *_tmp_166_rule(Parser *p); static void *_tmp_167_rule(Parser *p); static void *_tmp_168_rule(Parser *p); -static asdl_seq *_loop0_169_rule(Parser *p); -static asdl_seq *_loop0_170_rule(Parser *p); -static asdl_seq *_loop0_171_rule(Parser *p); -static asdl_seq *_loop1_172_rule(Parser *p); -static void *_tmp_173_rule(Parser *p); -static asdl_seq *_loop0_174_rule(Parser *p); -static void *_tmp_175_rule(Parser *p); -static asdl_seq *_loop0_176_rule(Parser *p); -static asdl_seq *_loop1_177_rule(Parser *p); -static void *_tmp_178_rule(Parser *p); -static void *_tmp_179_rule(Parser *p); -static void *_tmp_180_rule(Parser *p); -static asdl_seq *_loop0_181_rule(Parser *p); -static void *_tmp_182_rule(Parser *p); -static void *_tmp_183_rule(Parser *p); -static asdl_seq *_loop1_184_rule(Parser *p); -static void *_tmp_185_rule(Parser *p); -static asdl_seq *_loop0_186_rule(Parser *p); -static asdl_seq *_loop0_187_rule(Parser *p); -static asdl_seq *_loop0_188_rule(Parser *p); -static asdl_seq *_loop0_190_rule(Parser *p); -static asdl_seq *_gather_189_rule(Parser *p); -static void *_tmp_191_rule(Parser *p); -static asdl_seq *_loop0_192_rule(Parser *p); -static void *_tmp_193_rule(Parser *p); -static asdl_seq *_loop0_194_rule(Parser *p); -static asdl_seq *_loop1_195_rule(Parser *p); -static asdl_seq *_loop1_196_rule(Parser *p); -static void *_tmp_197_rule(Parser *p); -static void *_tmp_198_rule(Parser *p); -static asdl_seq *_loop0_199_rule(Parser *p); -static void *_tmp_200_rule(Parser *p); -static void *_tmp_201_rule(Parser *p); -static void *_tmp_202_rule(Parser *p); -static void *_tmp_203_rule(Parser *p); -static asdl_seq *_loop0_205_rule(Parser *p); -static asdl_seq *_gather_204_rule(Parser *p); -static asdl_seq *_loop0_207_rule(Parser *p); -static asdl_seq *_gather_206_rule(Parser *p); -static asdl_seq *_loop0_209_rule(Parser *p); -static asdl_seq *_gather_208_rule(Parser *p); -static asdl_seq *_loop0_211_rule(Parser *p); -static asdl_seq *_gather_210_rule(Parser *p); -static asdl_seq *_loop0_213_rule(Parser *p); -static asdl_seq *_gather_212_rule(Parser *p); -static void *_tmp_214_rule(Parser *p); -static asdl_seq *_loop0_215_rule(Parser *p); -static asdl_seq *_loop1_216_rule(Parser *p); -static void *_tmp_217_rule(Parser *p); -static asdl_seq *_loop0_218_rule(Parser *p); -static asdl_seq *_loop1_219_rule(Parser *p); -static void *_tmp_220_rule(Parser *p); -static void *_tmp_221_rule(Parser *p); -static void *_tmp_222_rule(Parser *p); -static void *_tmp_223_rule(Parser *p); -static void *_tmp_224_rule(Parser *p); -static void *_tmp_225_rule(Parser *p); -static void *_tmp_226_rule(Parser *p); -static void *_tmp_227_rule(Parser *p); -static void *_tmp_228_rule(Parser *p); -static void *_tmp_229_rule(Parser *p); -static void *_tmp_230_rule(Parser *p); -static void *_tmp_231_rule(Parser *p); -static void *_tmp_232_rule(Parser *p); -static asdl_seq *_loop0_234_rule(Parser *p); -static asdl_seq *_gather_233_rule(Parser *p); -static void *_tmp_235_rule(Parser *p); -static void *_tmp_236_rule(Parser *p); -static void *_tmp_237_rule(Parser *p); -static void *_tmp_238_rule(Parser *p); -static void *_tmp_239_rule(Parser *p); -static void *_tmp_240_rule(Parser *p); -static void *_tmp_241_rule(Parser *p); -static asdl_seq *_loop0_242_rule(Parser *p); -static void *_tmp_243_rule(Parser *p); -static void *_tmp_244_rule(Parser *p); -static void *_tmp_245_rule(Parser *p); -static void *_tmp_246_rule(Parser *p); -static void *_tmp_247_rule(Parser *p); -static void *_tmp_248_rule(Parser *p); -static void *_tmp_249_rule(Parser *p); -static void *_tmp_250_rule(Parser *p); -static void *_tmp_251_rule(Parser *p); -static void *_tmp_252_rule(Parser *p); -static void *_tmp_253_rule(Parser *p); -static void *_tmp_254_rule(Parser *p); -static void *_tmp_255_rule(Parser *p); -static void *_tmp_256_rule(Parser *p); -static void *_tmp_257_rule(Parser *p); -static void *_tmp_258_rule(Parser *p); -static void *_tmp_259_rule(Parser *p); -static void *_tmp_260_rule(Parser *p); -static void *_tmp_261_rule(Parser *p); -static void *_tmp_262_rule(Parser *p); -static void *_tmp_263_rule(Parser *p); -static void *_tmp_264_rule(Parser *p); -static void *_tmp_265_rule(Parser *p); -static void *_tmp_266_rule(Parser *p); -static void *_tmp_267_rule(Parser *p); -static asdl_seq *_loop0_268_rule(Parser *p); -static void *_tmp_269_rule(Parser *p); -static void *_tmp_270_rule(Parser *p); -static void *_tmp_271_rule(Parser *p); -static void *_tmp_272_rule(Parser *p); -static void *_tmp_273_rule(Parser *p); -static void *_tmp_274_rule(Parser *p); -static asdl_seq *_loop0_276_rule(Parser *p); -static asdl_seq *_gather_275_rule(Parser *p); -static void *_tmp_277_rule(Parser *p); -static void *_tmp_278_rule(Parser *p); -static void *_tmp_279_rule(Parser *p); -static void *_tmp_280_rule(Parser *p); -static void *_tmp_281_rule(Parser *p); -static void *_tmp_282_rule(Parser *p); -static void *_tmp_283_rule(Parser *p); +static void *_tmp_169_rule(Parser *p); // file: statements? $ @@ -1319,7 +1091,7 @@ func_type_rule(Parser *p) Token * _literal; Token * _literal_1; Token * _literal_2; - asdl_seq * _loop0_2_var; + asdl_seq * _loop0_1_var; void *a; expr_ty b; Token * endmarker_var; @@ -1334,7 +1106,7 @@ func_type_rule(Parser *p) && (b = expression_rule(p)) // expression && - (_loop0_2_var = _loop0_2_rule(p)) // NEWLINE* + (_loop0_1_var = _loop0_1_rule(p)) // NEWLINE* && (endmarker_var = _PyPegen_expect_token(p, ENDMARKER)) // token='ENDMARKER' ) @@ -1379,7 +1151,7 @@ statements_rule(Parser *p) D(fprintf(stderr, "%*c> statements[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement+")); asdl_seq * a; if ( - (a = _loop1_3_rule(p)) // statement+ + (a = _loop1_2_rule(p)) // statement+ ) { D(fprintf(stderr, "%*c+ statements[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "statement+")); @@ -1820,7 +1592,7 @@ simple_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> simple_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('import' | 'from') import_stmt")); stmt_ty import_stmt_var; if ( - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_6_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_5_rule, p) && (import_stmt_var = import_stmt_rule(p)) // import_stmt ) @@ -2094,7 +1866,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('def' | '@' | 'async') function_def")); stmt_ty function_def_var; if ( - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_7_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_6_rule, p) && (function_def_var = function_def_rule(p)) // function_def ) @@ -2136,7 +1908,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('class' | '@') class_def")); stmt_ty class_def_var; if ( - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_8_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_7_rule, p) && (class_def_var = class_def_rule(p)) // class_def ) @@ -2157,7 +1929,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('with' | 'async') with_stmt")); stmt_ty with_stmt_var; if ( - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_9_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_8_rule, p) && (with_stmt_var = with_stmt_rule(p)) // with_stmt ) @@ -2178,7 +1950,7 @@ compound_stmt_rule(Parser *p) D(fprintf(stderr, "%*c> compound_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&('for' | 'async') for_stmt")); stmt_ty for_stmt_var; if ( - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_10_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_9_rule, p) && (for_stmt_var = for_stmt_rule(p)) // for_stmt ) @@ -2261,8 +2033,8 @@ compound_stmt_rule(Parser *p) // assignment: // | NAME ':' expression ['=' annotated_rhs] // | ('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs] -// | ((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT? -// | single_target augassign ~ (yield_expr | star_expressions) +// | ((star_targets '='))+ annotated_rhs !'=' TYPE_COMMENT? +// | single_target augassign ~ annotated_rhs // | invalid_assignment static stmt_ty assignment_rule(Parser *p) @@ -2302,7 +2074,7 @@ assignment_rule(Parser *p) && (b = expression_rule(p)) // expression && - (c = _tmp_11_rule(p), !p->error_indicator) // ['=' annotated_rhs] + (c = _tmp_10_rule(p), !p->error_indicator) // ['=' annotated_rhs] ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ':' expression ['=' annotated_rhs]")); @@ -2338,13 +2110,13 @@ assignment_rule(Parser *p) expr_ty b; void *c; if ( - (a = _tmp_12_rule(p)) // '(' single_target ')' | single_subscript_attribute_target + (a = _tmp_11_rule(p)) // '(' single_target ')' | single_subscript_attribute_target && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && (b = expression_rule(p)) // expression && - (c = _tmp_13_rule(p), !p->error_indicator) // ['=' annotated_rhs] + (c = _tmp_10_rule(p), !p->error_indicator) // ['=' annotated_rhs] ) { D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); @@ -2369,26 +2141,26 @@ assignment_rule(Parser *p) D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('(' single_target ')' | single_subscript_attribute_target) ':' expression ['=' annotated_rhs]")); } - { // ((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT? + { // ((star_targets '='))+ annotated_rhs !'=' TYPE_COMMENT? if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); + D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ annotated_rhs !'=' TYPE_COMMENT?")); asdl_expr_seq* a; - void *b; + expr_ty b; void *tc; if ( - (a = (asdl_expr_seq*)_loop1_14_rule(p)) // ((star_targets '='))+ + (a = (asdl_expr_seq*)_loop1_12_rule(p)) // ((star_targets '='))+ && - (b = _tmp_15_rule(p)) // yield_expr | star_expressions + (b = annotated_rhs_rule(p)) // annotated_rhs && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' && (tc = _PyPegen_expect_token(p, TYPE_COMMENT), !p->error_indicator) // TYPE_COMMENT? ) { - D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); + D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((star_targets '='))+ annotated_rhs !'=' TYPE_COMMENT?")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -2408,18 +2180,18 @@ assignment_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "((star_targets '='))+ (yield_expr | star_expressions) !'=' TYPE_COMMENT?")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "((star_targets '='))+ annotated_rhs !'=' TYPE_COMMENT?")); } - { // single_target augassign ~ (yield_expr | star_expressions) + { // single_target augassign ~ annotated_rhs if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); + D(fprintf(stderr, "%*c> assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ annotated_rhs")); int _cut_var = 0; expr_ty a; AugOperator* b; - void *c; + expr_ty c; if ( (a = single_target_rule(p)) // single_target && @@ -2427,10 +2199,10 @@ assignment_rule(Parser *p) && (_cut_var = 1) && - (c = _tmp_16_rule(p)) // yield_expr | star_expressions + (c = annotated_rhs_rule(p)) // annotated_rhs ) { - D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); + D(fprintf(stderr, "%*c+ assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_target augassign ~ annotated_rhs")); Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); if (_token == NULL) { p->level--; @@ -2450,7 +2222,7 @@ assignment_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s assignment[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_target augassign ~ (yield_expr | star_expressions)")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_target augassign ~ annotated_rhs")); if (_cut_var) { p->level--; return NULL; @@ -2982,7 +2754,7 @@ raise_stmt_rule(Parser *p) && (a = expression_rule(p)) // expression && - (b = _tmp_17_rule(p), !p->error_indicator) // ['from' expression] + (b = _tmp_13_rule(p), !p->error_indicator) // ['from' expression] ) { D(fprintf(stderr, "%*c+ raise_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'raise' expression ['from' expression]")); @@ -3079,7 +2851,7 @@ global_stmt_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 526)) // token='global' && - (a = (asdl_expr_seq*)_gather_18_rule(p)) // ','.NAME+ + (a = (asdl_expr_seq*)_gather_15_rule(p)) // ','.NAME+ ) { D(fprintf(stderr, "%*c+ global_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'global' ','.NAME+")); @@ -3143,7 +2915,7 @@ nonlocal_stmt_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 527)) // token='nonlocal' && - (a = (asdl_expr_seq*)_gather_20_rule(p)) // ','.NAME+ + (a = (asdl_expr_seq*)_gather_15_rule(p)) // ','.NAME+ ) { D(fprintf(stderr, "%*c+ nonlocal_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'nonlocal' ','.NAME+")); @@ -3209,7 +2981,7 @@ del_stmt_rule(Parser *p) && (a = del_targets_rule(p)) // del_targets && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_22_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_16_rule, p) ) { D(fprintf(stderr, "%*c+ del_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'del' del_targets &(';' | NEWLINE)")); @@ -3356,7 +3128,7 @@ assert_stmt_rule(Parser *p) && (a = expression_rule(p)) // expression && - (b = _tmp_23_rule(p), !p->error_indicator) // [',' expression] + (b = _tmp_17_rule(p), !p->error_indicator) // [',' expression] ) { D(fprintf(stderr, "%*c+ assert_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'assert' expression [',' expression]")); @@ -3565,7 +3337,7 @@ import_from_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && - (a = _loop0_24_rule(p)) // (('.' | '...'))* + (a = _loop0_18_rule(p)) // (('.' | '...'))* && (b = dotted_name_rule(p)) // dotted_name && @@ -3609,7 +3381,7 @@ import_from_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && - (a = _loop1_25_rule(p)) // (('.' | '...'))+ + (a = _loop1_19_rule(p)) // (('.' | '...'))+ && (_keyword_1 = _PyPegen_expect_token(p, 622)) // token='import' && @@ -3804,7 +3576,7 @@ import_from_as_names_rule(Parser *p) D(fprintf(stderr, "%*c> import_from_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); asdl_alias_seq* a; if ( - (a = (asdl_alias_seq*)_gather_26_rule(p)) // ','.import_from_as_name+ + (a = (asdl_alias_seq*)_gather_21_rule(p)) // ','.import_from_as_name+ ) { D(fprintf(stderr, "%*c+ import_from_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.import_from_as_name+")); @@ -3859,7 +3631,7 @@ import_from_as_name_rule(Parser *p) if ( (a = _PyPegen_name_token(p)) // NAME && - (b = _tmp_28_rule(p), !p->error_indicator) // ['as' NAME] + (b = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] ) { D(fprintf(stderr, "%*c+ import_from_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME ['as' NAME]")); @@ -3911,7 +3683,7 @@ dotted_as_names_rule(Parser *p) D(fprintf(stderr, "%*c> dotted_as_names[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); asdl_alias_seq* a; if ( - (a = (asdl_alias_seq*)_gather_29_rule(p)) // ','.dotted_as_name+ + (a = (asdl_alias_seq*)_gather_24_rule(p)) // ','.dotted_as_name+ ) { D(fprintf(stderr, "%*c+ dotted_as_names[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.dotted_as_name+")); @@ -3966,7 +3738,7 @@ dotted_as_name_rule(Parser *p) if ( (a = dotted_name_rule(p)) // dotted_name && - (b = _tmp_31_rule(p), !p->error_indicator) // ['as' NAME] + (b = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] ) { D(fprintf(stderr, "%*c+ dotted_as_name[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name ['as' NAME]")); @@ -4217,7 +3989,7 @@ decorators_rule(Parser *p) D(fprintf(stderr, "%*c> decorators[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_loop1_32_rule(p)) // (('@' named_expression NEWLINE))+ + (a = (asdl_expr_seq*)_loop1_25_rule(p)) // (('@' named_expression NEWLINE))+ ) { D(fprintf(stderr, "%*c+ decorators[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(('@' named_expression NEWLINE))+")); @@ -4366,7 +4138,7 @@ class_def_raw_rule(Parser *p) && (t = type_params_rule(p), !p->error_indicator) // type_params? && - (b = _tmp_33_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (b = _tmp_26_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -4539,7 +4311,7 @@ function_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (a = _tmp_34_rule(p), !p->error_indicator) // ['->' expression] + (a = _tmp_27_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -4602,7 +4374,7 @@ function_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (a = _tmp_35_rule(p), !p->error_indicator) // ['->' expression] + (a = _tmp_27_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -4727,9 +4499,9 @@ parameters_rule(Parser *p) if ( (a = slash_no_default_rule(p)) // slash_no_default && - (b = (asdl_arg_seq*)_loop0_36_rule(p)) // param_no_default* + (b = (asdl_arg_seq*)_loop0_28_rule(p)) // param_no_default* && - (c = _loop0_37_rule(p)) // param_with_default* + (c = _loop0_29_rule(p)) // param_with_default* && (d = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4759,7 +4531,7 @@ parameters_rule(Parser *p) if ( (a = slash_with_default_rule(p)) // slash_with_default && - (b = _loop0_38_rule(p)) // param_with_default* + (b = _loop0_29_rule(p)) // param_with_default* && (c = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4787,9 +4559,9 @@ parameters_rule(Parser *p) asdl_seq * b; void *c; if ( - (a = (asdl_arg_seq*)_loop1_39_rule(p)) // param_no_default+ + (a = (asdl_arg_seq*)_loop1_30_rule(p)) // param_no_default+ && - (b = _loop0_40_rule(p)) // param_with_default* + (b = _loop0_29_rule(p)) // param_with_default* && (c = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4816,7 +4588,7 @@ parameters_rule(Parser *p) asdl_seq * a; void *b; if ( - (a = _loop1_41_rule(p)) // param_with_default+ + (a = _loop1_31_rule(p)) // param_with_default+ && (b = star_etc_rule(p), !p->error_indicator) // star_etc? ) @@ -4887,7 +4659,7 @@ slash_no_default_rule(Parser *p) Token * _literal_1; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_42_rule(p)) // param_no_default+ + (a = (asdl_arg_seq*)_loop1_30_rule(p)) // param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -4916,7 +4688,7 @@ slash_no_default_rule(Parser *p) Token * _literal; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_43_rule(p)) // param_no_default+ + (a = (asdl_arg_seq*)_loop1_30_rule(p)) // param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -4968,9 +4740,9 @@ slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_44_rule(p)) // param_no_default* + (a = _loop0_28_rule(p)) // param_no_default* && - (b = _loop1_45_rule(p)) // param_with_default+ + (b = _loop1_31_rule(p)) // param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -5000,9 +4772,9 @@ slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_46_rule(p)) // param_no_default* + (a = _loop0_28_rule(p)) // param_no_default* && - (b = _loop1_47_rule(p)) // param_with_default+ + (b = _loop1_31_rule(p)) // param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -5080,7 +4852,7 @@ star_etc_rule(Parser *p) && (a = param_no_default_rule(p)) // param_no_default && - (b = _loop0_48_rule(p)) // param_maybe_default* + (b = _loop0_32_rule(p)) // param_maybe_default* && (c = kwds_rule(p), !p->error_indicator) // kwds? ) @@ -5113,7 +4885,7 @@ star_etc_rule(Parser *p) && (a = param_no_default_star_annotation_rule(p)) // param_no_default_star_annotation && - (b = _loop0_49_rule(p)) // param_maybe_default* + (b = _loop0_32_rule(p)) // param_maybe_default* && (c = kwds_rule(p), !p->error_indicator) // kwds? ) @@ -5146,7 +4918,7 @@ star_etc_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _loop1_50_rule(p)) // param_maybe_default+ + (b = _loop1_33_rule(p)) // param_maybe_default+ && (c = kwds_rule(p), !p->error_indicator) // kwds? ) @@ -6574,7 +6346,7 @@ with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = (asdl_withitem_seq*)_gather_51_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_35_rule(p)) // ','.with_item+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -6623,7 +6395,7 @@ with_stmt_rule(Parser *p) if ( (_keyword = _PyPegen_expect_token(p, 633)) // token='with' && - (a = (asdl_withitem_seq*)_gather_53_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_35_rule(p)) // ','.with_item+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6676,7 +6448,7 @@ with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = (asdl_withitem_seq*)_gather_55_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_35_rule(p)) // ','.with_item+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -6726,7 +6498,7 @@ with_stmt_rule(Parser *p) && (_keyword_1 = _PyPegen_expect_token(p, 633)) // token='with' && - (a = (asdl_withitem_seq*)_gather_57_rule(p)) // ','.with_item+ + (a = (asdl_withitem_seq*)_gather_35_rule(p)) // ','.with_item+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -6814,7 +6586,7 @@ with_item_rule(Parser *p) && (t = star_target_rule(p)) // star_target && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_59_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_36_rule, p) ) { D(fprintf(stderr, "%*c+ with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' star_target &(',' | ')' | ':')")); @@ -6985,7 +6757,7 @@ try_stmt_rule(Parser *p) && (b = block_rule(p)) // block && - (ex = (asdl_excepthandler_seq*)_loop1_60_rule(p)) // except_block+ + (ex = (asdl_excepthandler_seq*)_loop1_37_rule(p)) // except_block+ && (el = else_block_rule(p), !p->error_indicator) // else_block? && @@ -7033,7 +6805,7 @@ try_stmt_rule(Parser *p) && (b = block_rule(p)) // block && - (ex = (asdl_excepthandler_seq*)_loop1_61_rule(p)) // except_star_block+ + (ex = (asdl_excepthandler_seq*)_loop1_38_rule(p)) // except_star_block+ && (el = else_block_rule(p), !p->error_indicator) // else_block? && @@ -7129,7 +6901,7 @@ except_block_rule(Parser *p) && (e = expression_rule(p)) // expression && - (t = _tmp_62_rule(p), !p->error_indicator) // ['as' NAME] + (t = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7285,7 +7057,7 @@ except_star_block_rule(Parser *p) && (e = expression_rule(p)) // expression && - (t = _tmp_63_rule(p), !p->error_indicator) // ['as' NAME] + (t = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -7455,7 +7227,7 @@ match_stmt_rule(Parser *p) && (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' && - (cases = (asdl_match_case_seq*)_loop1_64_rule(p)) // case_block+ + (cases = (asdl_match_case_seq*)_loop1_39_rule(p)) // case_block+ && (dedent_var = _PyPegen_expect_token(p, DEDENT)) // token='DEDENT' ) @@ -7966,7 +7738,7 @@ or_pattern_rule(Parser *p) D(fprintf(stderr, "%*c> or_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); asdl_pattern_seq* patterns; if ( - (patterns = (asdl_pattern_seq*)_gather_65_rule(p)) // '|'.closed_pattern+ + (patterns = (asdl_pattern_seq*)_gather_41_rule(p)) // '|'.closed_pattern+ ) { D(fprintf(stderr, "%*c+ or_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'|'.closed_pattern+")); @@ -8219,7 +7991,7 @@ literal_pattern_rule(Parser *p) if ( (value = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_67_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_42_rule, p) ) { D(fprintf(stderr, "%*c+ literal_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -8453,7 +8225,7 @@ literal_expr_rule(Parser *p) if ( (signed_number_var = signed_number_rule(p)) // signed_number && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_68_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_42_rule, p) ) { D(fprintf(stderr, "%*c+ literal_expr[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "signed_number !('+' | '-')")); @@ -9053,7 +8825,7 @@ pattern_capture_target_rule(Parser *p) && (name = _PyPegen_name_token(p)) // NAME && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_69_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_43_rule, p) ) { D(fprintf(stderr, "%*c+ pattern_capture_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!\"_\" NAME !('.' | '(' | '=')")); @@ -9168,7 +8940,7 @@ value_pattern_rule(Parser *p) if ( (attr = attr_rule(p)) // attr && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_70_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_43_rule, p) ) { D(fprintf(stderr, "%*c+ value_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr !('.' | '(' | '=')")); @@ -9587,7 +9359,7 @@ maybe_sequence_pattern_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * patterns; if ( - (patterns = _gather_71_rule(p)) // ','.maybe_star_pattern+ + (patterns = _gather_45_rule(p)) // ','.maybe_star_pattern+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -9995,13 +9767,13 @@ items_pattern_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> items_pattern[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); - asdl_seq * _gather_73_var; + asdl_seq * _gather_47_var; if ( - (_gather_73_var = _gather_73_rule(p)) // ','.key_value_pattern+ + (_gather_47_var = _gather_47_rule(p)) // ','.key_value_pattern+ ) { D(fprintf(stderr, "%*c+ items_pattern[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.key_value_pattern+")); - _res = _gather_73_var; + _res = _gather_47_var; goto done; } p->mark = _mark; @@ -10037,7 +9809,7 @@ key_value_pattern_rule(Parser *p) void *key; pattern_ty pattern; if ( - (key = _tmp_75_rule(p)) // literal_expr | attr + (key = _tmp_48_rule(p)) // literal_expr | attr && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -10365,7 +10137,7 @@ positional_patterns_rule(Parser *p) D(fprintf(stderr, "%*c> positional_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.pattern+")); asdl_pattern_seq* args; if ( - (args = (asdl_pattern_seq*)_gather_76_rule(p)) // ','.pattern+ + (args = (asdl_pattern_seq*)_gather_50_rule(p)) // ','.pattern+ ) { D(fprintf(stderr, "%*c+ positional_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.pattern+")); @@ -10406,13 +10178,13 @@ keyword_patterns_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> keyword_patterns[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); - asdl_seq * _gather_78_var; + asdl_seq * _gather_52_var; if ( - (_gather_78_var = _gather_78_rule(p)) // ','.keyword_pattern+ + (_gather_52_var = _gather_52_rule(p)) // ','.keyword_pattern+ ) { D(fprintf(stderr, "%*c+ keyword_patterns[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.keyword_pattern+")); - _res = _gather_78_var; + _res = _gather_52_var; goto done; } p->mark = _mark; @@ -10638,7 +10410,7 @@ type_param_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_type_param_seq* a; if ( - (a = (asdl_type_param_seq*)_gather_80_rule(p)) // ','.type_param+ + (a = (asdl_type_param_seq*)_gather_54_rule(p)) // ','.type_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11008,7 +10780,7 @@ expressions_rule(Parser *p) if ( (a = expression_rule(p)) // expression && - (b = _loop1_82_rule(p)) // ((',' expression))+ + (b = _loop1_55_rule(p)) // ((',' expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11396,7 +11168,7 @@ star_expressions_rule(Parser *p) if ( (a = star_expression_rule(p)) // star_expression && - (b = _loop1_83_rule(p)) // ((',' star_expression))+ + (b = _loop1_56_rule(p)) // ((',' star_expression))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11595,7 +11367,7 @@ star_named_expressions_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_84_rule(p)) // ','.star_named_expression+ + (a = (asdl_expr_seq*)_gather_58_rule(p)) // ','.star_named_expression+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -11891,7 +11663,7 @@ disjunction_rule(Parser *p) if ( (a = conjunction_rule(p)) // conjunction && - (b = _loop1_86_rule(p)) // (('or' conjunction))+ + (b = _loop1_59_rule(p)) // (('or' conjunction))+ ) { D(fprintf(stderr, "%*c+ disjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "conjunction (('or' conjunction))+")); @@ -11979,7 +11751,7 @@ conjunction_rule(Parser *p) if ( (a = inversion_rule(p)) // inversion && - (b = _loop1_87_rule(p)) // (('and' inversion))+ + (b = _loop1_60_rule(p)) // (('and' inversion))+ ) { D(fprintf(stderr, "%*c+ conjunction[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "inversion (('and' inversion))+")); @@ -12151,7 +11923,7 @@ comparison_rule(Parser *p) if ( (a = bitwise_or_rule(p)) // bitwise_or && - (b = _loop1_88_rule(p)) // compare_op_bitwise_or_pair+ + (b = _loop1_61_rule(p)) // compare_op_bitwise_or_pair+ ) { D(fprintf(stderr, "%*c+ comparison[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or compare_op_bitwise_or_pair+")); @@ -12485,10 +12257,10 @@ noteq_bitwise_or_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> noteq_bitwise_or[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('!=') bitwise_or")); - void *_tmp_89_var; + void *_tmp_62_var; expr_ty a; if ( - (_tmp_89_var = _tmp_89_rule(p)) // '!=' + (_tmp_62_var = _tmp_62_rule(p)) // '!=' && (a = bitwise_or_rule(p)) // bitwise_or ) @@ -14536,7 +14308,7 @@ slices_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_90_rule(p)) // ','.(slice | starred_expression)+ + (a = (asdl_expr_seq*)_gather_64_rule(p)) // ','.(slice | starred_expression)+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -14608,7 +14380,7 @@ slice_rule(Parser *p) && (b = expression_rule(p), !p->error_indicator) // expression? && - (c = _tmp_92_rule(p), !p->error_indicator) // [':' expression?] + (c = _tmp_65_rule(p), !p->error_indicator) // [':' expression?] ) { D(fprintf(stderr, "%*c+ slice[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression? ':' expression? [':' expression?]")); @@ -14821,7 +14593,7 @@ atom_rule(Parser *p) D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&(STRING | FSTRING_START) strings")); expr_ty strings_var; if ( - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_93_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_66_rule, p) && (strings_var = strings_rule(p)) // strings ) @@ -14859,15 +14631,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - void *_tmp_94_var; + void *_tmp_67_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 7) // token='(' && - (_tmp_94_var = _tmp_94_rule(p)) // tuple | group | genexp + (_tmp_67_var = _tmp_67_rule(p)) // tuple | group | genexp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'(' (tuple | group | genexp)")); - _res = _tmp_94_var; + _res = _tmp_67_var; goto done; } p->mark = _mark; @@ -14880,15 +14652,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - void *_tmp_95_var; + void *_tmp_68_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 9) // token='[' && - (_tmp_95_var = _tmp_95_rule(p)) // list | listcomp + (_tmp_68_var = _tmp_68_rule(p)) // list | listcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'[' (list | listcomp)")); - _res = _tmp_95_var; + _res = _tmp_68_var; goto done; } p->mark = _mark; @@ -14901,15 +14673,15 @@ atom_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - void *_tmp_96_var; + void *_tmp_69_var; if ( _PyPegen_lookahead_with_int(1, _PyPegen_expect_token, p, 25) // token='{' && - (_tmp_96_var = _tmp_96_rule(p)) // dict | set | dictcomp | setcomp + (_tmp_69_var = _tmp_69_rule(p)) // dict | set | dictcomp | setcomp ) { D(fprintf(stderr, "%*c+ atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "&'{' (dict | set | dictcomp | setcomp)")); - _res = _tmp_96_var; + _res = _tmp_69_var; goto done; } p->mark = _mark; @@ -14980,7 +14752,7 @@ group_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_97_rule(p)) // yield_expr | named_expression + (a = _tmp_70_rule(p)) // yield_expr | named_expression && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -15181,9 +14953,9 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_no_default_rule(p)) // lambda_slash_no_default && - (b = (asdl_arg_seq*)_loop0_98_rule(p)) // lambda_param_no_default* + (b = (asdl_arg_seq*)_loop0_71_rule(p)) // lambda_param_no_default* && - (c = _loop0_99_rule(p)) // lambda_param_with_default* + (c = _loop0_72_rule(p)) // lambda_param_with_default* && (d = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15213,7 +14985,7 @@ lambda_parameters_rule(Parser *p) if ( (a = lambda_slash_with_default_rule(p)) // lambda_slash_with_default && - (b = _loop0_100_rule(p)) // lambda_param_with_default* + (b = _loop0_72_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15241,9 +15013,9 @@ lambda_parameters_rule(Parser *p) asdl_seq * b; void *c; if ( - (a = (asdl_arg_seq*)_loop1_101_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_73_rule(p)) // lambda_param_no_default+ && - (b = _loop0_102_rule(p)) // lambda_param_with_default* + (b = _loop0_72_rule(p)) // lambda_param_with_default* && (c = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15270,7 +15042,7 @@ lambda_parameters_rule(Parser *p) asdl_seq * a; void *b; if ( - (a = _loop1_103_rule(p)) // lambda_param_with_default+ + (a = _loop1_74_rule(p)) // lambda_param_with_default+ && (b = lambda_star_etc_rule(p), !p->error_indicator) // lambda_star_etc? ) @@ -15343,7 +15115,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal_1; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_104_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_73_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15372,7 +15144,7 @@ lambda_slash_no_default_rule(Parser *p) Token * _literal; asdl_arg_seq* a; if ( - (a = (asdl_arg_seq*)_loop1_105_rule(p)) // lambda_param_no_default+ + (a = (asdl_arg_seq*)_loop1_73_rule(p)) // lambda_param_no_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15424,9 +15196,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_106_rule(p)) // lambda_param_no_default* + (a = _loop0_71_rule(p)) // lambda_param_no_default* && - (b = _loop1_107_rule(p)) // lambda_param_with_default+ + (b = _loop1_74_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15456,9 +15228,9 @@ lambda_slash_with_default_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _loop0_108_rule(p)) // lambda_param_no_default* + (a = _loop0_71_rule(p)) // lambda_param_no_default* && - (b = _loop1_109_rule(p)) // lambda_param_with_default+ + (b = _loop1_74_rule(p)) // lambda_param_with_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -15535,7 +15307,7 @@ lambda_star_etc_rule(Parser *p) && (a = lambda_param_no_default_rule(p)) // lambda_param_no_default && - (b = _loop0_110_rule(p)) // lambda_param_maybe_default* + (b = _loop0_75_rule(p)) // lambda_param_maybe_default* && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -15568,7 +15340,7 @@ lambda_star_etc_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _loop1_111_rule(p)) // lambda_param_maybe_default+ + (b = _loop1_76_rule(p)) // lambda_param_maybe_default+ && (c = lambda_kwds_rule(p), !p->error_indicator) // lambda_kwds? ) @@ -16208,7 +15980,7 @@ fstring_full_format_spec_rule(Parser *p) if ( (colon = _PyPegen_expect_token(p, 11)) // token=':' && - (spec = _loop0_112_rule(p)) // fstring_format_spec* + (spec = _loop0_77_rule(p)) // fstring_format_spec* ) { D(fprintf(stderr, "%*c+ fstring_full_format_spec[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' fstring_format_spec*")); @@ -16326,7 +16098,7 @@ fstring_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' && - (b = _loop0_113_rule(p)) // fstring_middle* + (b = _loop0_78_rule(p)) // fstring_middle* && (c = _PyPegen_expect_token(p, FSTRING_END)) // token='FSTRING_END' ) @@ -16427,7 +16199,7 @@ strings_rule(Parser *p) D(fprintf(stderr, "%*c> strings[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((fstring | string))+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_loop1_114_rule(p)) // ((fstring | string))+ + (a = (asdl_expr_seq*)_loop1_79_rule(p)) // ((fstring | string))+ ) { D(fprintf(stderr, "%*c+ strings[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((fstring | string))+")); @@ -16560,7 +16332,7 @@ tuple_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_115_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] + (a = _tmp_80_rule(p), !p->error_indicator) // [star_named_expression ',' star_named_expressions?] && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) @@ -16775,7 +16547,7 @@ double_starred_kvpairs_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_116_rule(p)) // ','.double_starred_kvpair+ + (a = _gather_82_rule(p)) // ','.double_starred_kvpair+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -16934,7 +16706,7 @@ for_if_clauses_rule(Parser *p) D(fprintf(stderr, "%*c> for_if_clauses[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); asdl_comprehension_seq* a; if ( - (a = (asdl_comprehension_seq*)_loop1_118_rule(p)) // for_if_clause+ + (a = (asdl_comprehension_seq*)_loop1_83_rule(p)) // for_if_clause+ ) { D(fprintf(stderr, "%*c+ for_if_clauses[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "for_if_clause+")); @@ -16999,7 +16771,7 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_119_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_84_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async' 'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -17042,7 +16814,7 @@ for_if_clause_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - (c = (asdl_expr_seq*)_loop0_120_rule(p)) // (('if' disjunction))* + (c = (asdl_expr_seq*)_loop0_84_rule(p)) // (('if' disjunction))* ) { D(fprintf(stderr, "%*c+ for_if_clause[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for' star_targets 'in' ~ disjunction (('if' disjunction))*")); @@ -17321,7 +17093,7 @@ genexp_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (a = _tmp_121_rule(p)) // assignment_expression | expression !':=' + (a = _tmp_85_rule(p)) // assignment_expression | expression !':=' && (b = for_if_clauses_rule(p)) // for_if_clauses && @@ -17570,9 +17342,9 @@ args_rule(Parser *p) asdl_expr_seq* a; void *b; if ( - (a = (asdl_expr_seq*)_gather_122_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (a = (asdl_expr_seq*)_gather_87_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ && - (b = _tmp_124_rule(p), !p->error_indicator) // [',' kwargs] + (b = _tmp_88_rule(p), !p->error_indicator) // [',' kwargs] ) { D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ [',' kwargs]")); @@ -17662,11 +17434,11 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_125_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_90_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_127_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_92_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -17688,13 +17460,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_129_var; + asdl_seq * _gather_90_var; if ( - (_gather_129_var = _gather_129_rule(p)) // ','.kwarg_or_starred+ + (_gather_90_var = _gather_90_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_129_var; + _res = _gather_90_var; goto done; } p->mark = _mark; @@ -17707,13 +17479,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_131_var; + asdl_seq * _gather_92_var; if ( - (_gather_131_var = _gather_131_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_92_var = _gather_92_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_131_var; + _res = _gather_92_var; goto done; } p->mark = _mark; @@ -18124,7 +17896,7 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_133_rule(p)) // ((',' star_target))* + (b = _loop0_93_rule(p)) // ((',' star_target))* && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18180,7 +17952,7 @@ star_targets_list_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_134_rule(p)) // ','.star_target+ + (a = (asdl_expr_seq*)_gather_95_rule(p)) // ','.star_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18230,7 +18002,7 @@ star_targets_tuple_seq_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop1_136_rule(p)) // ((',' star_target))+ + (b = _loop1_96_rule(p)) // ((',' star_target))+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -18318,7 +18090,7 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_137_rule(p)) // !'*' star_target + (a = _tmp_97_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -19241,7 +19013,7 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_138_rule(p)) // ','.del_target+ + (a = (asdl_expr_seq*)_gather_99_rule(p)) // ','.del_target+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) @@ -19599,7 +19371,7 @@ type_expressions_rule(Parser *p) expr_ty b; expr_ty c; if ( - (a = _gather_140_rule(p)) // ','.expression+ + (a = _gather_101_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19638,7 +19410,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_142_rule(p)) // ','.expression+ + (a = _gather_101_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19671,7 +19443,7 @@ type_expressions_rule(Parser *p) asdl_seq * a; expr_ty b; if ( - (a = _gather_144_rule(p)) // ','.expression+ + (a = _gather_101_rule(p)) // ','.expression+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -19791,7 +19563,7 @@ type_expressions_rule(Parser *p) D(fprintf(stderr, "%*c> type_expressions[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.expression+")); asdl_expr_seq* a; if ( - (a = (asdl_expr_seq*)_gather_146_rule(p)) // ','.expression+ + (a = (asdl_expr_seq*)_gather_101_rule(p)) // ','.expression+ ) { D(fprintf(stderr, "%*c+ type_expressions[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.expression+")); @@ -19842,7 +19614,7 @@ func_type_comment_rule(Parser *p) && (t = _PyPegen_expect_token(p, TYPE_COMMENT)) // token='TYPE_COMMENT' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_148_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_102_rule, p) ) { D(fprintf(stderr, "%*c+ func_type_comment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE TYPE_COMMENT &(NEWLINE INDENT)")); @@ -19928,15 +19700,15 @@ invalid_arguments_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_arguments[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' ','.(starred_expression !'=')+")); - asdl_seq * _gather_150_var; - void *_tmp_149_var; + asdl_seq * _gather_105_var; + void *_tmp_103_var; Token * a; if ( - (_tmp_149_var = _tmp_149_rule(p)) // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs + (_tmp_103_var = _tmp_103_rule(p)) // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs && (a = _PyPegen_expect_token(p, 12)) // token=',' && - (_gather_150_var = _gather_150_rule(p)) // ','.(starred_expression !'=')+ + (_gather_105_var = _gather_105_rule(p)) // ','.(starred_expression !'=')+ ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "((','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) | kwargs) ',' ','.(starred_expression !'=')+")); @@ -19970,7 +19742,7 @@ invalid_arguments_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_152_rule(p), !p->error_indicator) // [args | expression for_if_clauses] + (_opt_var = _tmp_106_rule(p), !p->error_indicator) // [args | expression for_if_clauses] ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -20030,13 +19802,13 @@ invalid_arguments_rule(Parser *p) expr_ty a; Token * b; if ( - (_opt_var = _tmp_153_rule(p), !p->error_indicator) // [(args ',')] + (_opt_var = _tmp_107_rule(p), !p->error_indicator) // [(args ',')] && (a = _PyPegen_name_token(p)) // NAME && (b = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_154_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_108_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "[(args ',')] NAME '=' &(',' | ')')")); @@ -20174,7 +19946,7 @@ invalid_kwarg_rule(Parser *p) Token* a; Token * b; if ( - (a = (Token*)_tmp_155_rule(p)) // 'True' | 'False' | 'None' + (a = (Token*)_tmp_109_rule(p)) // 'True' | 'False' | 'None' && (b = _PyPegen_expect_token(p, 22)) // token='=' ) @@ -20234,7 +20006,7 @@ invalid_kwarg_rule(Parser *p) expr_ty a; Token * b; if ( - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_156_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_110_rule, p) && (a = expression_rule(p)) // expression && @@ -20575,7 +20347,7 @@ invalid_expression_rule(Parser *p) expr_ty a; expr_ty b; if ( - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_157_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_111_rule, p) && (a = disjunction_rule(p)) // disjunction && @@ -20611,7 +20383,7 @@ invalid_expression_rule(Parser *p) && (b = disjunction_rule(p)) // disjunction && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_158_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_112_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "disjunction 'if' disjunction !('else' | ':')")); @@ -20732,7 +20504,7 @@ invalid_named_expression_rule(Parser *p) && (b = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_159_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_113_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '=' bitwise_or !('=' | ':=')")); @@ -20758,7 +20530,7 @@ invalid_named_expression_rule(Parser *p) Token * b; expr_ty bitwise_or_var; if ( - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_160_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_114_rule, p) && (a = bitwise_or_rule(p)) // bitwise_or && @@ -20766,7 +20538,7 @@ invalid_named_expression_rule(Parser *p) && (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_161_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_113_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_named_expression[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!(list | tuple | genexp | 'True' | 'None' | 'False') bitwise_or '=' bitwise_or !('=' | ':=')")); @@ -20846,7 +20618,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_162_var; + asdl_seq * _loop0_115_var; expr_ty a; expr_ty expression_var; if ( @@ -20854,7 +20626,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_162_var = _loop0_162_rule(p)) // star_named_expressions* + (_loop0_115_var = _loop0_115_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -20911,10 +20683,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_163_var; + asdl_seq * _loop0_116_var; expr_ty a; if ( - (_loop0_163_var = _loop0_163_rule(p)) // ((star_targets '='))* + (_loop0_116_var = _loop0_116_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -20941,10 +20713,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_164_var; + asdl_seq * _loop0_116_var; expr_ty a; if ( - (_loop0_164_var = _loop0_164_rule(p)) // ((star_targets '='))* + (_loop0_116_var = _loop0_116_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -21200,11 +20972,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_165_var; + void *_tmp_117_var; expr_ty a; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_165_var = _tmp_165_rule(p)) // '[' | '(' | '{' + (_tmp_117_var = _tmp_117_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -21231,12 +21003,12 @@ invalid_comprehension_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' star_named_expressions for_if_clauses")); Token * _literal; - void *_tmp_166_var; + void *_tmp_118_var; expr_ty a; asdl_expr_seq* b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_166_var = _tmp_166_rule(p)) // '[' | '{' + (_tmp_118_var = _tmp_118_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21266,12 +21038,12 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '{') star_named_expression ',' for_if_clauses")); - void *_tmp_167_var; + void *_tmp_118_var; expr_ty a; Token * b; asdl_comprehension_seq* for_if_clauses_var; if ( - (_tmp_167_var = _tmp_167_rule(p)) // '[' | '{' + (_tmp_118_var = _tmp_118_rule(p)) // '[' | '{' && (a = star_named_expression_rule(p)) // star_named_expression && @@ -21406,13 +21178,13 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slash_no_default | slash_with_default) param_maybe_default* '/'")); - asdl_seq * _loop0_169_var; - void *_tmp_168_var; + asdl_seq * _loop0_32_var; + void *_tmp_119_var; Token * a; if ( - (_tmp_168_var = _tmp_168_rule(p)) // slash_no_default | slash_with_default + (_tmp_119_var = _tmp_119_rule(p)) // slash_no_default | slash_with_default && - (_loop0_169_var = _loop0_169_rule(p)) // param_maybe_default* + (_loop0_32_var = _loop0_32_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21436,7 +21208,7 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default? param_no_default* invalid_parameters_helper param_no_default")); - asdl_seq * _loop0_170_var; + asdl_seq * _loop0_28_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -21444,7 +21216,7 @@ invalid_parameters_rule(Parser *p) if ( (_opt_var = slash_no_default_rule(p), !p->error_indicator) // slash_no_default? && - (_loop0_170_var = _loop0_170_rule(p)) // param_no_default* + (_loop0_28_var = _loop0_28_rule(p)) // param_no_default* && (invalid_parameters_helper_var = invalid_parameters_helper_rule(p)) // invalid_parameters_helper && @@ -21470,18 +21242,18 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* '(' param_no_default+ ','? ')'")); - asdl_seq * _loop0_171_var; - asdl_seq * _loop1_172_var; + asdl_seq * _loop0_28_var; + asdl_seq * _loop1_30_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_171_var = _loop0_171_rule(p)) // param_no_default* + (_loop0_28_var = _loop0_28_rule(p)) // param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_loop1_172_var = _loop1_172_rule(p)) // param_no_default+ + (_loop1_30_var = _loop1_30_rule(p)) // param_no_default+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -21508,22 +21280,22 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(slash_no_default | slash_with_default)] param_maybe_default* '*' (',' | param_no_default) param_maybe_default* '/'")); Token * _literal; - asdl_seq * _loop0_174_var; - asdl_seq * _loop0_176_var; + asdl_seq * _loop0_32_var; + asdl_seq * _loop0_32_var_1; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_175_var; + void *_tmp_120_var; Token * a; if ( - (_opt_var = _tmp_173_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] + (_opt_var = _tmp_119_rule(p), !p->error_indicator) // [(slash_no_default | slash_with_default)] && - (_loop0_174_var = _loop0_174_rule(p)) // param_maybe_default* + (_loop0_32_var = _loop0_32_rule(p)) // param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_175_var = _tmp_175_rule(p)) // ',' | param_no_default + (_tmp_120_var = _tmp_120_rule(p)) // ',' | param_no_default && - (_loop0_176_var = _loop0_176_rule(p)) // param_maybe_default* + (_loop0_32_var_1 = _loop0_32_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -21548,10 +21320,10 @@ invalid_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_177_var; + asdl_seq * _loop1_33_var; Token * a; if ( - (_loop1_177_var = _loop1_177_rule(p)) // param_maybe_default+ + (_loop1_33_var = _loop1_33_rule(p)) // param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -21600,7 +21372,7 @@ invalid_default_rule(Parser *p) if ( (a = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_178_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_121_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_default[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' &(')' | ',')")); @@ -21645,12 +21417,12 @@ invalid_star_etc_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); - void *_tmp_179_var; + void *_tmp_122_var; Token * a; if ( (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_179_var = _tmp_179_rule(p)) // ')' | ',' (')' | '**') + (_tmp_122_var = _tmp_122_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -21733,20 +21505,20 @@ invalid_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_181_var; - void *_tmp_180_var; - void *_tmp_182_var; + asdl_seq * _loop0_32_var; + void *_tmp_123_var; + void *_tmp_123_var_1; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_180_var = _tmp_180_rule(p)) // param_no_default | ',' + (_tmp_123_var = _tmp_123_rule(p)) // param_no_default | ',' && - (_loop0_181_var = _loop0_181_rule(p)) // param_maybe_default* + (_loop0_32_var = _loop0_32_rule(p)) // param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_182_var = _tmp_182_rule(p)) // param_no_default | ',' + (_tmp_123_var_1 = _tmp_123_rule(p)) // param_no_default | ',' ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (param_no_default | ',') param_maybe_default* '*' (param_no_default | ',')")); @@ -21861,7 +21633,7 @@ invalid_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_183_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_124_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' param ',' ('*' | '**' | '/')")); @@ -21926,13 +21698,13 @@ invalid_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_184_var; + asdl_seq * _loop1_31_var; if ( - (_loop1_184_var = _loop1_184_rule(p)) // param_with_default+ + (_loop1_31_var = _loop1_31_rule(p)) // param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_184_var; + _res = _loop1_31_var; goto done; } p->mark = _mark; @@ -21997,13 +21769,13 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(lambda_slash_no_default | lambda_slash_with_default) lambda_param_maybe_default* '/'")); - asdl_seq * _loop0_186_var; - void *_tmp_185_var; + asdl_seq * _loop0_75_var; + void *_tmp_125_var; Token * a; if ( - (_tmp_185_var = _tmp_185_rule(p)) // lambda_slash_no_default | lambda_slash_with_default + (_tmp_125_var = _tmp_125_rule(p)) // lambda_slash_no_default | lambda_slash_with_default && - (_loop0_186_var = _loop0_186_rule(p)) // lambda_param_maybe_default* + (_loop0_75_var = _loop0_75_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -22027,7 +21799,7 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default? lambda_param_no_default* invalid_lambda_parameters_helper lambda_param_no_default")); - asdl_seq * _loop0_187_var; + asdl_seq * _loop0_71_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings arg_ty a; @@ -22035,7 +21807,7 @@ invalid_lambda_parameters_rule(Parser *p) if ( (_opt_var = lambda_slash_no_default_rule(p), !p->error_indicator) // lambda_slash_no_default? && - (_loop0_187_var = _loop0_187_rule(p)) // lambda_param_no_default* + (_loop0_71_var = _loop0_71_rule(p)) // lambda_param_no_default* && (invalid_lambda_parameters_helper_var = invalid_lambda_parameters_helper_rule(p)) // invalid_lambda_parameters_helper && @@ -22061,18 +21833,18 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* '(' ','.lambda_param+ ','? ')'")); - asdl_seq * _gather_189_var; - asdl_seq * _loop0_188_var; + asdl_seq * _gather_127_var; + asdl_seq * _loop0_71_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; Token * b; if ( - (_loop0_188_var = _loop0_188_rule(p)) // lambda_param_no_default* + (_loop0_71_var = _loop0_71_rule(p)) // lambda_param_no_default* && (a = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_189_var = _gather_189_rule(p)) // ','.lambda_param+ + (_gather_127_var = _gather_127_rule(p)) // ','.lambda_param+ && (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -22099,22 +21871,22 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "[(lambda_slash_no_default | lambda_slash_with_default)] lambda_param_maybe_default* '*' (',' | lambda_param_no_default) lambda_param_maybe_default* '/'")); Token * _literal; - asdl_seq * _loop0_192_var; - asdl_seq * _loop0_194_var; + asdl_seq * _loop0_75_var; + asdl_seq * _loop0_75_var_1; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_193_var; + void *_tmp_128_var; Token * a; if ( - (_opt_var = _tmp_191_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] + (_opt_var = _tmp_125_rule(p), !p->error_indicator) // [(lambda_slash_no_default | lambda_slash_with_default)] && - (_loop0_192_var = _loop0_192_rule(p)) // lambda_param_maybe_default* + (_loop0_75_var = _loop0_75_rule(p)) // lambda_param_maybe_default* && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_193_var = _tmp_193_rule(p)) // ',' | lambda_param_no_default + (_tmp_128_var = _tmp_128_rule(p)) // ',' | lambda_param_no_default && - (_loop0_194_var = _loop0_194_rule(p)) // lambda_param_maybe_default* + (_loop0_75_var_1 = _loop0_75_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 17)) // token='/' ) @@ -22139,10 +21911,10 @@ invalid_lambda_parameters_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default+ '/' '*'")); Token * _literal; - asdl_seq * _loop1_195_var; + asdl_seq * _loop1_76_var; Token * a; if ( - (_loop1_195_var = _loop1_195_rule(p)) // lambda_param_maybe_default+ + (_loop1_76_var = _loop1_76_rule(p)) // lambda_param_maybe_default+ && (_literal = _PyPegen_expect_token(p, 17)) // token='/' && @@ -22213,13 +21985,13 @@ invalid_lambda_parameters_helper_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters_helper[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_196_var; + asdl_seq * _loop1_74_var; if ( - (_loop1_196_var = _loop1_196_rule(p)) // lambda_param_with_default+ + (_loop1_74_var = _loop1_74_rule(p)) // lambda_param_with_default+ ) { D(fprintf(stderr, "%*c+ invalid_lambda_parameters_helper[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_196_var; + _res = _loop1_74_var; goto done; } p->mark = _mark; @@ -22255,11 +22027,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_197_var; + void *_tmp_129_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_197_var = _tmp_197_rule(p)) // ':' | ',' (':' | '**') + (_tmp_129_var = _tmp_129_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -22312,20 +22084,20 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); Token * _literal; - asdl_seq * _loop0_199_var; - void *_tmp_198_var; - void *_tmp_200_var; + asdl_seq * _loop0_75_var; + void *_tmp_130_var; + void *_tmp_130_var_1; Token * a; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_198_var = _tmp_198_rule(p)) // lambda_param_no_default | ',' + (_tmp_130_var = _tmp_130_rule(p)) // lambda_param_no_default | ',' && - (_loop0_199_var = _loop0_199_rule(p)) // lambda_param_maybe_default* + (_loop0_75_var = _loop0_75_rule(p)) // lambda_param_maybe_default* && (a = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_200_var = _tmp_200_rule(p)) // lambda_param_no_default | ',' + (_tmp_130_var_1 = _tmp_130_rule(p)) // lambda_param_no_default | ',' ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (lambda_param_no_default | ',') lambda_param_maybe_default* '*' (lambda_param_no_default | ',')")); @@ -22443,7 +22215,7 @@ invalid_lambda_kwds_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 12)) // token=',' && - (a = (Token*)_tmp_201_rule(p)) // '*' | '**' | '/' + (a = (Token*)_tmp_124_rule(p)) // '*' | '**' | '/' ) { D(fprintf(stderr, "%*c+ invalid_lambda_kwds[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**' lambda_param ',' ('*' | '**' | '/')")); @@ -22549,7 +22321,7 @@ invalid_with_item_rule(Parser *p) && (a = expression_rule(p)) // expression && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_202_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_36_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_with_item[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression 'as' expression &(',' | ')' | ':')")); @@ -22593,13 +22365,13 @@ invalid_for_if_clause_rule(Parser *p) Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings - void *_tmp_203_var; + void *_tmp_131_var; if ( (_opt_var = _PyPegen_expect_token(p, 682), !p->error_indicator) // 'async'? && (_keyword = _PyPegen_expect_token(p, 678)) // token='for' && - (_tmp_203_var = _tmp_203_rule(p)) // bitwise_or ((',' bitwise_or))* ','? + (_tmp_131_var = _tmp_131_rule(p)) // bitwise_or ((',' bitwise_or))* ','? && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 679) // token='in' ) @@ -22774,14 +22546,14 @@ invalid_import_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_import[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import' ','.dotted_name+ 'from' dotted_name")); - asdl_seq * _gather_204_var; + asdl_seq * _gather_133_var; Token * _keyword; Token * a; expr_ty dotted_name_var; if ( (a = _PyPegen_expect_token(p, 622)) // token='import' && - (_gather_204_var = _gather_204_rule(p)) // ','.dotted_name+ + (_gather_133_var = _gather_133_rule(p)) // ','.dotted_name+ && (_keyword = _PyPegen_expect_token(p, 621)) // token='from' && @@ -22928,7 +22700,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ NEWLINE")); - asdl_seq * _gather_206_var; + asdl_seq * _gather_135_var; Token * _keyword; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -22938,7 +22710,7 @@ invalid_with_stmt_rule(Parser *p) && (_keyword = _PyPegen_expect_token(p, 633)) // token='with' && - (_gather_206_var = _gather_206_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_135_var = _gather_135_rule(p)) // ','.(expression ['as' star_target])+ && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -22962,7 +22734,7 @@ invalid_with_stmt_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' NEWLINE")); - asdl_seq * _gather_208_var; + asdl_seq * _gather_137_var; Token * _keyword; Token * _literal; Token * _literal_1; @@ -22978,7 +22750,7 @@ invalid_with_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_208_var = _gather_208_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_137_var = _gather_137_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -23027,7 +22799,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' ','.(expression ['as' star_target])+ ':' NEWLINE !INDENT")); - asdl_seq * _gather_210_var; + asdl_seq * _gather_135_var; Token * _literal; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings @@ -23038,7 +22810,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (a = _PyPegen_expect_token(p, 633)) // token='with' && - (_gather_210_var = _gather_210_rule(p)) // ','.(expression ['as' star_target])+ + (_gather_135_var = _gather_135_rule(p)) // ','.(expression ['as' star_target])+ && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23066,7 +22838,7 @@ invalid_with_stmt_indent_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_with_stmt_indent[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'? 'with' '(' ','.(expressions ['as' star_target])+ ','? ')' ':' NEWLINE !INDENT")); - asdl_seq * _gather_212_var; + asdl_seq * _gather_137_var; Token * _literal; Token * _literal_1; Token * _literal_2; @@ -23083,7 +22855,7 @@ invalid_with_stmt_indent_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 7)) // token='(' && - (_gather_212_var = _gather_212_rule(p)) // ','.(expressions ['as' star_target])+ + (_gather_137_var = _gather_137_rule(p)) // ','.(expressions ['as' star_target])+ && (_opt_var_1 = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? && @@ -23180,7 +22952,7 @@ invalid_try_stmt_rule(Parser *p) && (block_var = block_rule(p)) // block && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_214_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_138_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_try_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'try' ':' block !('except' | 'finally')")); @@ -23205,8 +22977,8 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_215_var; - asdl_seq * _loop1_216_var; + asdl_seq * _loop0_139_var; + asdl_seq * _loop1_37_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; @@ -23217,9 +22989,9 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_215_var = _loop0_215_rule(p)) // block* + (_loop0_139_var = _loop0_139_rule(p)) // block* && - (_loop1_216_var = _loop1_216_rule(p)) // except_block+ + (_loop1_37_var = _loop1_37_rule(p)) // except_block+ && (a = _PyPegen_expect_token(p, 663)) // token='except' && @@ -23227,7 +22999,7 @@ invalid_try_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_217_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23254,8 +23026,8 @@ invalid_try_stmt_rule(Parser *p) Token * _keyword; Token * _literal; Token * _literal_1; - asdl_seq * _loop0_218_var; - asdl_seq * _loop1_219_var; + asdl_seq * _loop0_139_var; + asdl_seq * _loop1_38_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings Token * a; @@ -23264,13 +23036,13 @@ invalid_try_stmt_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_218_var = _loop0_218_rule(p)) // block* + (_loop0_139_var = _loop0_139_rule(p)) // block* && - (_loop1_219_var = _loop1_219_rule(p)) // except_star_block+ + (_loop1_38_var = _loop1_38_rule(p)) // except_star_block+ && (a = _PyPegen_expect_token(p, 663)) // token='except' && - (_opt_var = _tmp_220_rule(p), !p->error_indicator) // [expression ['as' NAME]] + (_opt_var = _tmp_140_rule(p), !p->error_indicator) // [expression ['as' NAME]] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23333,7 +23105,7 @@ invalid_except_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_221_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23367,7 +23139,7 @@ invalid_except_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_222_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23493,7 +23265,7 @@ invalid_except_star_stmt_rule(Parser *p) && (expressions_var = expressions_rule(p)) // expressions && - (_opt_var = _tmp_223_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' ) @@ -23530,7 +23302,7 @@ invalid_except_star_stmt_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_224_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -23555,14 +23327,14 @@ invalid_except_star_stmt_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_except_star_stmt[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); Token * _literal; - void *_tmp_225_var; + void *_tmp_141_var; Token * a; if ( (a = _PyPegen_expect_token(p, 663)) // token='except' && (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_225_var = _tmp_225_rule(p)) // NEWLINE | ':' + (_tmp_141_var = _tmp_141_rule(p)) // NEWLINE | ':' ) { D(fprintf(stderr, "%*c+ invalid_except_star_stmt[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except' '*' (NEWLINE | ':')")); @@ -23703,7 +23475,7 @@ invalid_except_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_226_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -23797,7 +23569,7 @@ invalid_except_star_stmt_indent_rule(Parser *p) && (expression_var = expression_rule(p)) // expression && - (_opt_var = _tmp_227_rule(p), !p->error_indicator) // ['as' NAME] + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24159,7 +23931,7 @@ invalid_class_argument_pattern_rule(Parser *p) asdl_pattern_seq* a; asdl_seq* keyword_patterns_var; if ( - (_opt_var = _tmp_228_rule(p), !p->error_indicator) // [positional_patterns ','] + (_opt_var = _tmp_142_rule(p), !p->error_indicator) // [positional_patterns ','] && (keyword_patterns_var = keyword_patterns_rule(p)) // keyword_patterns && @@ -24652,7 +24424,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_3 = _tmp_229_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_3 = _tmp_27_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24711,7 +24483,7 @@ invalid_def_raw_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' && - (_opt_var_3 = _tmp_230_rule(p), !p->error_indicator) // ['->' expression] + (_opt_var_3 = _tmp_27_rule(p), !p->error_indicator) // ['->' expression] && (_literal_2 = _PyPegen_expect_forced_token(p, 11, ":")) // forced_token=':' && @@ -24769,7 +24541,7 @@ invalid_class_def_raw_rule(Parser *p) && (_opt_var = type_params_rule(p), !p->error_indicator) // type_params? && - (_opt_var_1 = _tmp_231_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var_1 = _tmp_26_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) @@ -24808,7 +24580,7 @@ invalid_class_def_raw_rule(Parser *p) && (_opt_var = type_params_rule(p), !p->error_indicator) // type_params? && - (_opt_var_1 = _tmp_232_rule(p), !p->error_indicator) // ['(' arguments? ')'] + (_opt_var_1 = _tmp_26_rule(p), !p->error_indicator) // ['(' arguments? ')'] && (_literal = _PyPegen_expect_token(p, 11)) // token=':' && @@ -24858,11 +24630,11 @@ invalid_double_starred_kvpairs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_double_starred_kvpairs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - asdl_seq * _gather_233_var; + asdl_seq * _gather_82_var; Token * _literal; void *invalid_kvpair_var; if ( - (_gather_233_var = _gather_233_rule(p)) // ','.double_starred_kvpair+ + (_gather_82_var = _gather_82_rule(p)) // ','.double_starred_kvpair+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && @@ -24870,7 +24642,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.double_starred_kvpair+ ',' invalid_kvpair")); - _res = _PyPegen_dummy_name(p, _gather_233_var, _literal, invalid_kvpair_var); + _res = _PyPegen_dummy_name(p, _gather_82_var, _literal, invalid_kvpair_var); goto done; } p->mark = _mark; @@ -24923,7 +24695,7 @@ invalid_double_starred_kvpairs_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_235_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_143_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_double_starred_kvpairs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -25033,7 +24805,7 @@ invalid_kvpair_rule(Parser *p) && (a = _PyPegen_expect_token(p, 11)) // token=':' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_236_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_143_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_kvpair[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ':' &('}' | ',')")); @@ -25321,7 +25093,7 @@ invalid_replacement_field_rule(Parser *p) && (annotated_rhs_var = annotated_rhs_rule(p)) // annotated_rhs && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_237_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_144_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs !('=' | '!' | ':' | '}')")); @@ -25353,7 +25125,7 @@ invalid_replacement_field_rule(Parser *p) && (_literal_1 = _PyPegen_expect_token(p, 22)) // token='=' && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_238_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_145_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '=' !('!' | ':' | '}')")); @@ -25417,9 +25189,9 @@ invalid_replacement_field_rule(Parser *p) && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_239_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_146_rule(p), !p->error_indicator) // ['!' NAME] && - _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_240_rule, p) + _PyPegen_lookahead(0, (void *(*)(Parser *)) _tmp_147_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_replacement_field[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] !(':' | '}')")); @@ -25443,7 +25215,7 @@ invalid_replacement_field_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_replacement_field[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{' annotated_rhs '='? ['!' NAME] ':' fstring_format_spec* !'}'")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_242_var; + asdl_seq * _loop0_77_var; void *_opt_var; UNUSED(_opt_var); // Silence compiler warnings void *_opt_var_1; @@ -25456,11 +25228,11 @@ invalid_replacement_field_rule(Parser *p) && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_241_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_146_rule(p), !p->error_indicator) // ['!' NAME] && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && - (_loop0_242_var = _loop0_242_rule(p)) // fstring_format_spec* + (_loop0_77_var = _loop0_77_rule(p)) // fstring_format_spec* && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -25497,7 +25269,7 @@ invalid_replacement_field_rule(Parser *p) && (_opt_var = _PyPegen_expect_token(p, 22), !p->error_indicator) // '='? && - (_opt_var_1 = _tmp_243_rule(p), !p->error_indicator) // ['!' NAME] + (_opt_var_1 = _tmp_146_rule(p), !p->error_indicator) // ['!' NAME] && _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 26) // token='}' ) @@ -25544,7 +25316,7 @@ invalid_conversion_character_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 54)) // token='!' && - _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_244_rule, p) + _PyPegen_lookahead(1, (void *(*)(Parser *)) _tmp_147_rule, p) ) { D(fprintf(stderr, "%*c+ invalid_conversion_character[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' &(':' | '}')")); @@ -25611,14 +25383,14 @@ invalid_arithmetic_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_arithmetic[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "sum ('+' | '-' | '*' | '/' | '%' | '//' | '@') 'not' inversion")); - void *_tmp_245_var; + void *_tmp_148_var; Token * a; expr_ty b; expr_ty sum_var; if ( (sum_var = sum_rule(p)) // sum && - (_tmp_245_var = _tmp_245_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' + (_tmp_148_var = _tmp_148_rule(p)) // '+' | '-' | '*' | '/' | '%' | '//' | '@' && (a = _PyPegen_expect_token(p, 687)) // token='not' && @@ -25663,11 +25435,11 @@ invalid_factor_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_factor[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('+' | '-' | '~') 'not' factor")); - void *_tmp_246_var; + void *_tmp_149_var; Token * a; expr_ty b; if ( - (_tmp_246_var = _tmp_246_rule(p)) // '+' | '-' | '~' + (_tmp_149_var = _tmp_149_rule(p)) // '+' | '-' | '~' && (a = _PyPegen_expect_token(p, 687)) // token='not' && @@ -25806,76 +25578,9 @@ _loop0_1_rule(Parser *p) return _seq; } -// _loop0_2: NEWLINE -static asdl_seq * -_loop0_2_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // NEWLINE - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_2[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); - Token * newline_var; - while ( - (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' - ) - { - _res = newline_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_2[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_3: statement +// _loop1_2: statement static asdl_seq * -_loop1_3_rule(Parser *p) +_loop1_2_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -25900,7 +25605,7 @@ _loop1_3_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); + D(fprintf(stderr, "%*c> _loop1_2[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "statement")); asdl_stmt_seq* statement_var; while ( (statement_var = statement_rule(p)) // statement @@ -25923,7 +25628,7 @@ _loop1_3_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_3[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_2[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "statement")); } if (_n == 0 || p->error_indicator) { @@ -25945,9 +25650,9 @@ _loop1_3_rule(Parser *p) return _seq; } -// _loop0_5: ';' simple_stmt +// _loop0_3: ';' simple_stmt static asdl_seq * -_loop0_5_rule(Parser *p) +_loop0_3_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -25972,7 +25677,7 @@ _loop0_5_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); + D(fprintf(stderr, "%*c> _loop0_3[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';' simple_stmt")); Token * _literal; stmt_ty elem; while ( @@ -26004,7 +25709,7 @@ _loop0_5_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_5[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_3[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "';' simple_stmt")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26021,7 +25726,7 @@ _loop0_5_rule(Parser *p) return _seq; } -// _gather_4: simple_stmt _loop0_5 +// _gather_4: simple_stmt _loop0_3 static asdl_seq * _gather_4_rule(Parser *p) { @@ -26034,27 +25739,27 @@ _gather_4_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // simple_stmt _loop0_5 + { // simple_stmt _loop0_3 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_5")); + D(fprintf(stderr, "%*c> _gather_4[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_3")); stmt_ty elem; asdl_seq * seq; if ( (elem = simple_stmt_rule(p)) // simple_stmt && - (seq = _loop0_5_rule(p)) // _loop0_5 + (seq = _loop0_3_rule(p)) // _loop0_3 ) { - D(fprintf(stderr, "%*c+ _gather_4[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_5")); + D(fprintf(stderr, "%*c+ _gather_4[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "simple_stmt _loop0_3")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; D(fprintf(stderr, "%*c%s _gather_4[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "simple_stmt _loop0_5")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "simple_stmt _loop0_3")); } _res = NULL; done: @@ -26062,9 +25767,9 @@ _gather_4_rule(Parser *p) return _res; } -// _tmp_6: 'import' | 'from' +// _tmp_5: 'import' | 'from' static void * -_tmp_6_rule(Parser *p) +_tmp_5_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26080,18 +25785,18 @@ _tmp_6_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); + D(fprintf(stderr, "%*c> _tmp_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'import'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 622)) // token='import' ) { - D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import'")); + D(fprintf(stderr, "%*c+ _tmp_5[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'import'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_5[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'import'")); } { // 'from' @@ -26099,18 +25804,18 @@ _tmp_6_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); + D(fprintf(stderr, "%*c> _tmp_5[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 621)) // token='from' ) { - D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from'")); + D(fprintf(stderr, "%*c+ _tmp_5[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_5[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from'")); } _res = NULL; @@ -26119,9 +25824,9 @@ _tmp_6_rule(Parser *p) return _res; } -// _tmp_7: 'def' | '@' | 'async' +// _tmp_6: 'def' | '@' | 'async' static void * -_tmp_7_rule(Parser *p) +_tmp_6_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26137,18 +25842,18 @@ _tmp_7_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); + D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'def'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 683)) // token='def' ) { - D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); + D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'def'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'def'")); } { // '@' @@ -26156,18 +25861,18 @@ _tmp_7_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); } { // 'async' @@ -26175,18 +25880,18 @@ _tmp_7_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c> _tmp_6[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 682)) // token='async' ) { - D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c+ _tmp_6[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_6[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'")); } _res = NULL; @@ -26195,9 +25900,9 @@ _tmp_7_rule(Parser *p) return _res; } -// _tmp_8: 'class' | '@' +// _tmp_7: 'class' | '@' static void * -_tmp_8_rule(Parser *p) +_tmp_7_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26213,18 +25918,18 @@ _tmp_8_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); + D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'class'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 685)) // token='class' ) { - D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); + D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'class'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'class'")); } { // '@' @@ -26232,18 +25937,18 @@ _tmp_8_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c> _tmp_7[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c+ _tmp_7[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_7[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); } _res = NULL; @@ -26252,9 +25957,9 @@ _tmp_8_rule(Parser *p) return _res; } -// _tmp_9: 'with' | 'async' +// _tmp_8: 'with' | 'async' static void * -_tmp_9_rule(Parser *p) +_tmp_8_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26270,18 +25975,18 @@ _tmp_9_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); + D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'with'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 633)) // token='with' ) { - D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); + D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'with'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'with'")); } { // 'async' @@ -26289,18 +25994,18 @@ _tmp_9_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c> _tmp_8[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 682)) // token='async' ) { - D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c+ _tmp_8[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_8[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'")); } _res = NULL; @@ -26309,9 +26014,9 @@ _tmp_9_rule(Parser *p) return _res; } -// _tmp_10: 'for' | 'async' +// _tmp_9: 'for' | 'async' static void * -_tmp_10_rule(Parser *p) +_tmp_9_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26327,18 +26032,18 @@ _tmp_10_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); + D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'for'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 678)) // token='for' ) { - D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); + D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'for'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'for'")); } { // 'async' @@ -26346,18 +26051,18 @@ _tmp_10_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c> _tmp_9[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'async'")); Token * _keyword; if ( (_keyword = _PyPegen_expect_token(p, 682)) // token='async' ) { - D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); + D(fprintf(stderr, "%*c+ _tmp_9[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'async'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_9[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'async'")); } _res = NULL; @@ -26366,9 +26071,9 @@ _tmp_10_rule(Parser *p) return _res; } -// _tmp_11: '=' annotated_rhs +// _tmp_10: '=' annotated_rhs static void * -_tmp_11_rule(Parser *p) +_tmp_10_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26384,7 +26089,7 @@ _tmp_11_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); + D(fprintf(stderr, "%*c> _tmp_10[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); Token * _literal; expr_ty d; if ( @@ -26393,7 +26098,7 @@ _tmp_11_rule(Parser *p) (d = annotated_rhs_rule(p)) // annotated_rhs ) { - D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); + D(fprintf(stderr, "%*c+ _tmp_10[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); _res = d; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26403,7 +26108,7 @@ _tmp_11_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_11[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_10[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'=' annotated_rhs")); } _res = NULL; @@ -26412,9 +26117,9 @@ _tmp_11_rule(Parser *p) return _res; } -// _tmp_12: '(' single_target ')' | single_subscript_attribute_target +// _tmp_11: '(' single_target ')' | single_subscript_attribute_target static void * -_tmp_12_rule(Parser *p) +_tmp_11_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26430,7 +26135,7 @@ _tmp_12_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); + D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); Token * _literal; Token * _literal_1; expr_ty b; @@ -26442,7 +26147,7 @@ _tmp_12_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_12[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); + D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' single_target ')'")); _res = b; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26452,7 +26157,7 @@ _tmp_12_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_12[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_11[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' single_target ')'")); } { // single_subscript_attribute_target @@ -26460,18 +26165,18 @@ _tmp_12_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); + D(fprintf(stderr, "%*c> _tmp_11[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); expr_ty single_subscript_attribute_target_var; if ( (single_subscript_attribute_target_var = single_subscript_attribute_target_rule(p)) // single_subscript_attribute_target ) { - D(fprintf(stderr, "%*c+ _tmp_12[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); + D(fprintf(stderr, "%*c+ _tmp_11[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "single_subscript_attribute_target")); _res = single_subscript_attribute_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_12[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_11[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "single_subscript_attribute_target")); } _res = NULL; @@ -26480,55 +26185,9 @@ _tmp_12_rule(Parser *p) return _res; } -// _tmp_13: '=' annotated_rhs -static void * -_tmp_13_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '=' annotated_rhs - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); - Token * _literal; - expr_ty d; - if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' - && - (d = annotated_rhs_rule(p)) // annotated_rhs - ) - { - D(fprintf(stderr, "%*c+ _tmp_13[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'=' annotated_rhs")); - _res = d; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_13[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'=' annotated_rhs")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_14: (star_targets '=') +// _loop1_12: (star_targets '=') static asdl_seq * -_loop1_14_rule(Parser *p) +_loop1_12_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26553,13 +26212,13 @@ _loop1_14_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_247_var; + D(fprintf(stderr, "%*c> _loop1_12[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_150_var; while ( - (_tmp_247_var = _tmp_247_rule(p)) // star_targets '=' + (_tmp_150_var = _tmp_150_rule(p)) // star_targets '=' ) { - _res = _tmp_247_var; + _res = _tmp_150_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -26576,7 +26235,7 @@ _loop1_14_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_14[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_12[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } if (_n == 0 || p->error_indicator) { @@ -26598,123 +26257,9 @@ _loop1_14_rule(Parser *p) return _seq; } -// _tmp_15: yield_expr | star_expressions -static void * -_tmp_15_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_15[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_15[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_15[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_15[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_16: yield_expr | star_expressions -static void * -_tmp_16_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // star_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); - expr_ty star_expressions_var; - if ( - (star_expressions_var = star_expressions_rule(p)) // star_expressions - ) - { - D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); - _res = star_expressions_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_17: 'from' expression +// _tmp_13: 'from' expression static void * -_tmp_17_rule(Parser *p) +_tmp_13_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26730,7 +26275,7 @@ _tmp_17_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); + D(fprintf(stderr, "%*c> _tmp_13[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'from' expression")); Token * _keyword; expr_ty z; if ( @@ -26739,7 +26284,7 @@ _tmp_17_rule(Parser *p) (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_17[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' expression")); + D(fprintf(stderr, "%*c+ _tmp_13[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'from' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -26749,7 +26294,7 @@ _tmp_17_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_17[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_13[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'from' expression")); } _res = NULL; @@ -26758,126 +26303,9 @@ _tmp_17_rule(Parser *p) return _res; } -// _loop0_19: ',' NAME -static asdl_seq * -_loop0_19_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' NAME - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _PyPegen_name_token(p)) // NAME - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_19[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' NAME")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_18: NAME _loop0_19 -static asdl_seq * -_gather_18_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // NAME _loop0_19 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_19")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = _PyPegen_name_token(p)) // NAME - && - (seq = _loop0_19_rule(p)) // _loop0_19 - ) - { - D(fprintf(stderr, "%*c+ _gather_18[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_19")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_18[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_19")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_21: ',' NAME +// _loop0_14: ',' NAME static asdl_seq * -_loop0_21_rule(Parser *p) +_loop0_14_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26902,7 +26330,7 @@ _loop0_21_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); + D(fprintf(stderr, "%*c> _loop0_14[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' NAME")); Token * _literal; expr_ty elem; while ( @@ -26934,7 +26362,7 @@ _loop0_21_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_21[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_14[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' NAME")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -26951,9 +26379,9 @@ _loop0_21_rule(Parser *p) return _seq; } -// _gather_20: NAME _loop0_21 +// _gather_15: NAME _loop0_14 static asdl_seq * -_gather_20_rule(Parser *p) +_gather_15_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -26964,27 +26392,27 @@ _gather_20_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // NAME _loop0_21 + { // NAME _loop0_14 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_21")); + D(fprintf(stderr, "%*c> _gather_15[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME _loop0_14")); expr_ty elem; asdl_seq * seq; if ( (elem = _PyPegen_name_token(p)) // NAME && - (seq = _loop0_21_rule(p)) // _loop0_21 + (seq = _loop0_14_rule(p)) // _loop0_14 ) { - D(fprintf(stderr, "%*c+ _gather_20[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_21")); + D(fprintf(stderr, "%*c+ _gather_15[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME _loop0_14")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_20[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_21")); + D(fprintf(stderr, "%*c%s _gather_15[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME _loop0_14")); } _res = NULL; done: @@ -26992,9 +26420,9 @@ _gather_20_rule(Parser *p) return _res; } -// _tmp_22: ';' | NEWLINE +// _tmp_16: ';' | NEWLINE static void * -_tmp_22_rule(Parser *p) +_tmp_16_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27010,18 +26438,18 @@ _tmp_22_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); + D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "';'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 13)) // token=';' ) { - D(fprintf(stderr, "%*c+ _tmp_22[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "';'")); + D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "';'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_22[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "';'")); } { // NEWLINE @@ -27029,18 +26457,18 @@ _tmp_22_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_16[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); Token * newline_var; if ( (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_22[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_16[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); _res = newline_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_22[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_16[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } _res = NULL; @@ -27049,9 +26477,9 @@ _tmp_22_rule(Parser *p) return _res; } -// _tmp_23: ',' expression +// _tmp_17: ',' expression static void * -_tmp_23_rule(Parser *p) +_tmp_17_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27067,7 +26495,7 @@ _tmp_23_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_17[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty z; if ( @@ -27076,7 +26504,7 @@ _tmp_23_rule(Parser *p) (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_23[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_17[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27086,7 +26514,7 @@ _tmp_23_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_23[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_17[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -27095,9 +26523,9 @@ _tmp_23_rule(Parser *p) return _res; } -// _loop0_24: ('.' | '...') +// _loop0_18: ('.' | '...') static asdl_seq * -_loop0_24_rule(Parser *p) +_loop0_18_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27122,13 +26550,13 @@ _loop0_24_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_248_var; + D(fprintf(stderr, "%*c> _loop0_18[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); + void *_tmp_151_var; while ( - (_tmp_248_var = _tmp_248_rule(p)) // '.' | '...' + (_tmp_151_var = _tmp_151_rule(p)) // '.' | '...' ) { - _res = _tmp_248_var; + _res = _tmp_151_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27145,7 +26573,7 @@ _loop0_24_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_24[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_18[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('.' | '...')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27162,9 +26590,9 @@ _loop0_24_rule(Parser *p) return _seq; } -// _loop1_25: ('.' | '...') +// _loop1_19: ('.' | '...') static asdl_seq * -_loop1_25_rule(Parser *p) +_loop1_19_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27189,13 +26617,13 @@ _loop1_25_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_249_var; + D(fprintf(stderr, "%*c> _loop1_19[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); + void *_tmp_151_var; while ( - (_tmp_249_var = _tmp_249_rule(p)) // '.' | '...' + (_tmp_151_var = _tmp_151_rule(p)) // '.' | '...' ) { - _res = _tmp_249_var; + _res = _tmp_151_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27212,7 +26640,7 @@ _loop1_25_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_25[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_19[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('.' | '...')")); } if (_n == 0 || p->error_indicator) { @@ -27234,9 +26662,9 @@ _loop1_25_rule(Parser *p) return _seq; } -// _loop0_27: ',' import_from_as_name +// _loop0_20: ',' import_from_as_name static asdl_seq * -_loop0_27_rule(Parser *p) +_loop0_20_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27261,7 +26689,7 @@ _loop0_27_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); + D(fprintf(stderr, "%*c> _loop0_20[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' import_from_as_name")); Token * _literal; alias_ty elem; while ( @@ -27293,7 +26721,7 @@ _loop0_27_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_27[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_20[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' import_from_as_name")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27310,9 +26738,9 @@ _loop0_27_rule(Parser *p) return _seq; } -// _gather_26: import_from_as_name _loop0_27 +// _gather_21: import_from_as_name _loop0_20 static asdl_seq * -_gather_26_rule(Parser *p) +_gather_21_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27323,27 +26751,27 @@ _gather_26_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // import_from_as_name _loop0_27 + { // import_from_as_name _loop0_20 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_27")); + D(fprintf(stderr, "%*c> _gather_21[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_20")); alias_ty elem; asdl_seq * seq; if ( (elem = import_from_as_name_rule(p)) // import_from_as_name && - (seq = _loop0_27_rule(p)) // _loop0_27 + (seq = _loop0_20_rule(p)) // _loop0_20 ) { - D(fprintf(stderr, "%*c+ _gather_26[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_27")); + D(fprintf(stderr, "%*c+ _gather_21[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "import_from_as_name _loop0_20")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_26[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_name _loop0_27")); + D(fprintf(stderr, "%*c%s _gather_21[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "import_from_as_name _loop0_20")); } _res = NULL; done: @@ -27351,9 +26779,9 @@ _gather_26_rule(Parser *p) return _res; } -// _tmp_28: 'as' NAME +// _tmp_22: 'as' NAME static void * -_tmp_28_rule(Parser *p) +_tmp_22_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27369,7 +26797,7 @@ _tmp_28_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c> _tmp_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); Token * _keyword; expr_ty z; if ( @@ -27378,7 +26806,7 @@ _tmp_28_rule(Parser *p) (z = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_28[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c+ _tmp_22[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27388,7 +26816,7 @@ _tmp_28_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_28[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_22[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); } _res = NULL; @@ -27397,9 +26825,9 @@ _tmp_28_rule(Parser *p) return _res; } -// _loop0_30: ',' dotted_as_name +// _loop0_23: ',' dotted_as_name static asdl_seq * -_loop0_30_rule(Parser *p) +_loop0_23_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27424,7 +26852,7 @@ _loop0_30_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); + D(fprintf(stderr, "%*c> _loop0_23[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_as_name")); Token * _literal; alias_ty elem; while ( @@ -27456,7 +26884,7 @@ _loop0_30_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_30[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_23[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_as_name")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27473,9 +26901,9 @@ _loop0_30_rule(Parser *p) return _seq; } -// _gather_29: dotted_as_name _loop0_30 +// _gather_24: dotted_as_name _loop0_23 static asdl_seq * -_gather_29_rule(Parser *p) +_gather_24_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27486,27 +26914,27 @@ _gather_29_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // dotted_as_name _loop0_30 + { // dotted_as_name _loop0_23 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_30")); + D(fprintf(stderr, "%*c> _gather_24[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_23")); alias_ty elem; asdl_seq * seq; if ( (elem = dotted_as_name_rule(p)) // dotted_as_name && - (seq = _loop0_30_rule(p)) // _loop0_30 + (seq = _loop0_23_rule(p)) // _loop0_23 ) { - D(fprintf(stderr, "%*c+ _gather_29[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_30")); + D(fprintf(stderr, "%*c+ _gather_24[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_as_name _loop0_23")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_29[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_as_name _loop0_30")); + D(fprintf(stderr, "%*c%s _gather_24[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_as_name _loop0_23")); } _res = NULL; done: @@ -27514,55 +26942,9 @@ _gather_29_rule(Parser *p) return _res; } -// _tmp_31: 'as' NAME -static void * -_tmp_31_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // 'as' NAME - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty z; - if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (z = _PyPegen_name_token(p)) // NAME - ) - { - D(fprintf(stderr, "%*c+ _tmp_31[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = z; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_31[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_32: ('@' named_expression NEWLINE) +// _loop1_25: ('@' named_expression NEWLINE) static asdl_seq * -_loop1_32_rule(Parser *p) +_loop1_25_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27587,13 +26969,13 @@ _loop1_32_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_250_var; + D(fprintf(stderr, "%*c> _loop1_25[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); + void *_tmp_152_var; while ( - (_tmp_250_var = _tmp_250_rule(p)) // '@' named_expression NEWLINE + (_tmp_152_var = _tmp_152_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_250_var; + _res = _tmp_152_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -27610,7 +26992,7 @@ _loop1_32_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_32[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_25[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('@' named_expression NEWLINE)")); } if (_n == 0 || p->error_indicator) { @@ -27632,9 +27014,9 @@ _loop1_32_rule(Parser *p) return _seq; } -// _tmp_33: '(' arguments? ')' +// _tmp_26: '(' arguments? ')' static void * -_tmp_33_rule(Parser *p) +_tmp_26_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27650,7 +27032,7 @@ _tmp_33_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_26[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); Token * _literal; Token * _literal_1; void *z; @@ -27662,7 +27044,7 @@ _tmp_33_rule(Parser *p) (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_33[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c+ _tmp_26[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27672,7 +27054,7 @@ _tmp_33_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_33[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_26[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); } _res = NULL; @@ -27681,9 +27063,9 @@ _tmp_33_rule(Parser *p) return _res; } -// _tmp_34: '->' expression +// _tmp_27: '->' expression static void * -_tmp_34_rule(Parser *p) +_tmp_27_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27699,7 +27081,7 @@ _tmp_34_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_27[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); Token * _literal; expr_ty z; if ( @@ -27708,7 +27090,7 @@ _tmp_34_rule(Parser *p) (z = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_34[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c+ _tmp_27[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -27718,7 +27100,7 @@ _tmp_34_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_34[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_27[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); } _res = NULL; @@ -27727,55 +27109,9 @@ _tmp_34_rule(Parser *p) return _res; } -// _tmp_35: '->' expression -static void * -_tmp_35_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '->' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); - Token * _literal; - expr_ty z; - if ( - (_literal = _PyPegen_expect_token(p, 51)) // token='->' - && - (z = expression_rule(p)) // expression - ) - { - D(fprintf(stderr, "%*c+ _tmp_35[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); - _res = z; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_35[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_36: param_no_default +// _loop0_28: param_no_default static asdl_seq * -_loop0_36_rule(Parser *p) +_loop0_28_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27800,7 +27136,7 @@ _loop0_36_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_28[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -27823,7 +27159,7 @@ _loop0_36_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_36[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_28[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27840,76 +27176,9 @@ _loop0_36_rule(Parser *p) return _seq; } -// _loop0_37: param_with_default -static asdl_seq * -_loop0_37_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); - NameDefaultPair* param_with_default_var; - while ( - (param_with_default_var = param_with_default_rule(p)) // param_with_default - ) - { - _res = param_with_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_37[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_38: param_with_default +// _loop0_29: param_with_default static asdl_seq * -_loop0_38_rule(Parser *p) +_loop0_29_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -27934,7 +27203,7 @@ _loop0_38_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop0_29[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -27957,7 +27226,7 @@ _loop0_38_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_38[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_29[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); @@ -27974,9 +27243,9 @@ _loop0_38_rule(Parser *p) return _seq; } -// _loop1_39: param_no_default +// _loop1_30: param_no_default static asdl_seq * -_loop1_39_rule(Parser *p) +_loop1_30_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28001,7 +27270,7 @@ _loop1_39_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop1_30[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -28024,7 +27293,7 @@ _loop1_39_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_39[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_30[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } if (_n == 0 || p->error_indicator) { @@ -28046,9 +27315,9 @@ _loop1_39_rule(Parser *p) return _seq; } -// _loop0_40: param_with_default +// _loop1_31: param_with_default static asdl_seq * -_loop0_40_rule(Parser *p) +_loop1_31_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28073,7 +27342,7 @@ _loop0_40_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -28096,9 +27365,14 @@ _loop0_40_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_40[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_31[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; + } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { PyMem_Free(_children); @@ -28113,9 +27387,9 @@ _loop0_40_rule(Parser *p) return _seq; } -// _loop1_41: param_with_default +// _loop0_32: param_maybe_default static asdl_seq * -_loop1_41_rule(Parser *p) +_loop0_32_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28135,18 +27409,18 @@ _loop1_41_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_with_default + { // param_maybe_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); - NameDefaultPair* param_with_default_var; + D(fprintf(stderr, "%*c> _loop0_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + NameDefaultPair* param_maybe_default_var; while ( - (param_with_default_var = param_with_default_rule(p)) // param_with_default + (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default ) { - _res = param_with_default_var; + _res = param_maybe_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28163,13 +27437,8 @@ _loop1_41_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_41[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_32[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28185,9 +27454,9 @@ _loop1_41_rule(Parser *p) return _seq; } -// _loop1_42: param_no_default +// _loop1_33: param_maybe_default static asdl_seq * -_loop1_42_rule(Parser *p) +_loop1_33_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28207,18 +27476,18 @@ _loop1_42_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_no_default + { // param_maybe_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; + D(fprintf(stderr, "%*c> _loop1_33[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); + NameDefaultPair* param_maybe_default_var; while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default + (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default ) { - _res = param_no_default_var; + _res = param_maybe_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28235,8 +27504,8 @@ _loop1_42_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_42[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c%s _loop1_33[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -28257,9 +27526,9 @@ _loop1_42_rule(Parser *p) return _seq; } -// _loop1_43: param_no_default +// _loop0_34: ',' with_item static asdl_seq * -_loop1_43_rule(Parser *p) +_loop0_34_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28279,18 +27548,27 @@ _loop1_43_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_no_default + { // ',' with_item if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; + D(fprintf(stderr, "%*c> _loop0_34[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + Token * _literal; + withitem_ty elem; while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = with_item_rule(p)) // with_item ) { - _res = param_no_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28307,13 +27585,8 @@ _loop1_43_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_43[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_34[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28329,9 +27602,9 @@ _loop1_43_rule(Parser *p) return _seq; } -// _loop0_44: param_no_default +// _gather_35: with_item _loop0_34 static asdl_seq * -_loop0_44_rule(Parser *p) +_gather_35_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28340,65 +27613,39 @@ _loop0_44_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_no_default + { // with_item _loop0_34 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default + D(fprintf(stderr, "%*c> _gather_35[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_34")); + withitem_ty elem; + asdl_seq * seq; + if ( + (elem = with_item_rule(p)) // with_item + && + (seq = _loop0_34_rule(p)) // _loop0_34 ) { - _res = param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _gather_35[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_34")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_44[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _gather_35[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_34")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop1_45: param_with_default -static asdl_seq * -_loop1_45_rule(Parser *p) +// _tmp_36: ',' | ')' | ':' +static void * +_tmp_36_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28407,70 +27654,74 @@ _loop1_45_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_with_default + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); - NameDefaultPair* param_with_default_var; - while ( - (param_with_default_var = param_with_default_rule(p)) // param_with_default + D(fprintf(stderr, "%*c> _tmp_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - _res = param_with_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_36[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + _res = _literal; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_45[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c%s _tmp_36[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + { // ')' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 8)) // token=')' + ) + { + D(fprintf(stderr, "%*c+ _tmp_36[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_36[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + { // ':' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_36[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + ) + { + D(fprintf(stderr, "%*c+ _tmp_36[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_36[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop0_46: param_no_default +// _loop1_37: except_block static asdl_seq * -_loop0_46_rule(Parser *p) +_loop1_37_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28490,18 +27741,18 @@ _loop0_46_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_no_default + { // except_block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; + D(fprintf(stderr, "%*c> _loop1_37[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); + excepthandler_ty except_block_var; while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default + (except_block_var = except_block_rule(p)) // except_block ) { - _res = param_no_default_var; + _res = except_block_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28518,8 +27769,13 @@ _loop0_46_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_46[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c%s _loop1_37[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28535,9 +27791,9 @@ _loop0_46_rule(Parser *p) return _seq; } -// _loop1_47: param_with_default +// _loop1_38: except_star_block static asdl_seq * -_loop1_47_rule(Parser *p) +_loop1_38_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28557,18 +27813,18 @@ _loop1_47_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_with_default + { // except_star_block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); - NameDefaultPair* param_with_default_var; + D(fprintf(stderr, "%*c> _loop1_38[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); + excepthandler_ty except_star_block_var; while ( - (param_with_default_var = param_with_default_rule(p)) // param_with_default + (except_star_block_var = except_star_block_rule(p)) // except_star_block ) { - _res = param_with_default_var; + _res = except_star_block_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28585,8 +27841,8 @@ _loop1_47_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_47[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c%s _loop1_38[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -28607,9 +27863,9 @@ _loop1_47_rule(Parser *p) return _seq; } -// _loop0_48: param_maybe_default +// _loop1_39: case_block static asdl_seq * -_loop0_48_rule(Parser *p) +_loop1_39_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28629,18 +27885,18 @@ _loop0_48_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_maybe_default + { // case_block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; + D(fprintf(stderr, "%*c> _loop1_39[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); + match_case_ty case_block_var; while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default + (case_block_var = case_block_rule(p)) // case_block ) { - _res = param_maybe_default_var; + _res = case_block_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28657,8 +27913,13 @@ _loop0_48_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_48[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c%s _loop1_39[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "case_block")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28674,9 +27935,9 @@ _loop0_48_rule(Parser *p) return _seq; } -// _loop0_49: param_maybe_default +// _loop0_40: '|' closed_pattern static asdl_seq * -_loop0_49_rule(Parser *p) +_loop0_40_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28696,18 +27957,27 @@ _loop0_49_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // param_maybe_default + { // '|' closed_pattern if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; + D(fprintf(stderr, "%*c> _loop0_40[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); + Token * _literal; + pattern_ty elem; while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default + (_literal = _PyPegen_expect_token(p, 18)) // token='|' + && + (elem = closed_pattern_rule(p)) // closed_pattern ) { - _res = param_maybe_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -28724,8 +27994,8 @@ _loop0_49_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_49[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c%s _loop0_40[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'|' closed_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28741,9 +28011,9 @@ _loop0_49_rule(Parser *p) return _seq; } -// _loop1_50: param_maybe_default +// _gather_41: closed_pattern _loop0_40 static asdl_seq * -_loop1_50_rule(Parser *p) +_gather_41_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28752,70 +28022,172 @@ _loop1_50_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); + { // closed_pattern _loop0_40 + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _gather_41[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_40")); + pattern_ty elem; + asdl_seq * seq; + if ( + (elem = closed_pattern_rule(p)) // closed_pattern + && + (seq = _loop0_40_rule(p)) // _loop0_40 + ) + { + D(fprintf(stderr, "%*c+ _gather_41[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_40")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_41[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "closed_pattern _loop0_40")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_42: '+' | '-' +static void * +_tmp_42_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { p->level--; return NULL; } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_maybe_default + void * _res = NULL; + int _mark = p->mark; + { // '+' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; - while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default + D(fprintf(stderr, "%*c> _tmp_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - _res = param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_42[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + _res = _literal; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_50[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); + D(fprintf(stderr, "%*c%s _tmp_42[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + { // '-' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_42[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 15)) // token='-' + ) + { + D(fprintf(stderr, "%*c+ _tmp_42[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_42[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_43: '.' | '(' | '=' +static void * +_tmp_43_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { p->level--; return NULL; } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + void * _res = NULL; + int _mark = p->mark; + { // '.' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 23)) // token='.' + ) + { + D(fprintf(stderr, "%*c+ _tmp_43[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_43[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); + } + { // '(' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 7)) // token='(' + ) + { + D(fprintf(stderr, "%*c+ _tmp_43[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_43[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); + } + { // '=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_43[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 22)) // token='=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_43[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_43[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); + } + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop0_52: ',' with_item +// _loop0_44: ',' maybe_star_pattern static asdl_seq * -_loop0_52_rule(Parser *p) +_loop0_44_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28835,18 +28207,18 @@ _loop0_52_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' with_item + { // ',' maybe_star_pattern if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_44[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); Token * _literal; - withitem_ty elem; + pattern_ty elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = with_item_rule(p)) // with_item + (elem = maybe_star_pattern_rule(p)) // maybe_star_pattern ) { _res = elem; @@ -28872,8 +28244,8 @@ _loop0_52_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_52[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c%s _loop0_44[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' maybe_star_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -28889,9 +28261,9 @@ _loop0_52_rule(Parser *p) return _seq; } -// _gather_51: with_item _loop0_52 +// _gather_45: maybe_star_pattern _loop0_44 static asdl_seq * -_gather_51_rule(Parser *p) +_gather_45_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28902,27 +28274,27 @@ _gather_51_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_52 + { // maybe_star_pattern _loop0_44 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_52")); - withitem_ty elem; + D(fprintf(stderr, "%*c> _gather_45[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_44")); + pattern_ty elem; asdl_seq * seq; if ( - (elem = with_item_rule(p)) // with_item + (elem = maybe_star_pattern_rule(p)) // maybe_star_pattern && - (seq = _loop0_52_rule(p)) // _loop0_52 + (seq = _loop0_44_rule(p)) // _loop0_44 ) { - D(fprintf(stderr, "%*c+ _gather_51[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_52")); + D(fprintf(stderr, "%*c+ _gather_45[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_44")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_51[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_52")); + D(fprintf(stderr, "%*c%s _gather_45[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "maybe_star_pattern _loop0_44")); } _res = NULL; done: @@ -28930,9 +28302,9 @@ _gather_51_rule(Parser *p) return _res; } -// _loop0_54: ',' with_item +// _loop0_46: ',' key_value_pattern static asdl_seq * -_loop0_54_rule(Parser *p) +_loop0_46_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -28952,18 +28324,18 @@ _loop0_54_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' with_item + { // ',' key_value_pattern if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_46[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); Token * _literal; - withitem_ty elem; + KeyPatternPair* elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = with_item_rule(p)) // with_item + (elem = key_value_pattern_rule(p)) // key_value_pattern ) { _res = elem; @@ -28989,8 +28361,8 @@ _loop0_54_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_54[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c%s _loop0_46[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' key_value_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -29006,9 +28378,9 @@ _loop0_54_rule(Parser *p) return _seq; } -// _gather_53: with_item _loop0_54 +// _gather_47: key_value_pattern _loop0_46 static asdl_seq * -_gather_53_rule(Parser *p) +_gather_47_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29019,27 +28391,84 @@ _gather_53_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_54 + { // key_value_pattern _loop0_46 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_54")); - withitem_ty elem; + D(fprintf(stderr, "%*c> _gather_47[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_46")); + KeyPatternPair* elem; asdl_seq * seq; if ( - (elem = with_item_rule(p)) // with_item + (elem = key_value_pattern_rule(p)) // key_value_pattern && - (seq = _loop0_54_rule(p)) // _loop0_54 + (seq = _loop0_46_rule(p)) // _loop0_46 ) { - D(fprintf(stderr, "%*c+ _gather_53[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_54")); + D(fprintf(stderr, "%*c+ _gather_47[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_46")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_53[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_54")); + D(fprintf(stderr, "%*c%s _gather_47[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "key_value_pattern _loop0_46")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_48: literal_expr | attr +static void * +_tmp_48_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // literal_expr + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); + expr_ty literal_expr_var; + if ( + (literal_expr_var = literal_expr_rule(p)) // literal_expr + ) + { + D(fprintf(stderr, "%*c+ _tmp_48[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "literal_expr")); + _res = literal_expr_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_48[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "literal_expr")); + } + { // attr + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_48[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); + expr_ty attr_var; + if ( + (attr_var = attr_rule(p)) // attr + ) + { + D(fprintf(stderr, "%*c+ _tmp_48[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr")); + _res = attr_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_48[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "attr")); } _res = NULL; done: @@ -29047,9 +28476,9 @@ _gather_53_rule(Parser *p) return _res; } -// _loop0_56: ',' with_item +// _loop0_49: ',' pattern static asdl_seq * -_loop0_56_rule(Parser *p) +_loop0_49_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29069,18 +28498,18 @@ _loop0_56_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' with_item + { // ',' pattern if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_49[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); Token * _literal; - withitem_ty elem; + pattern_ty elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = with_item_rule(p)) // with_item + (elem = pattern_rule(p)) // pattern ) { _res = elem; @@ -29106,8 +28535,8 @@ _loop0_56_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_56[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c%s _loop0_49[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -29123,9 +28552,9 @@ _loop0_56_rule(Parser *p) return _seq; } -// _gather_55: with_item _loop0_56 +// _gather_50: pattern _loop0_49 static asdl_seq * -_gather_55_rule(Parser *p) +_gather_50_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29136,27 +28565,27 @@ _gather_55_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_56 + { // pattern _loop0_49 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_56")); - withitem_ty elem; + D(fprintf(stderr, "%*c> _gather_50[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_49")); + pattern_ty elem; asdl_seq * seq; if ( - (elem = with_item_rule(p)) // with_item + (elem = pattern_rule(p)) // pattern && - (seq = _loop0_56_rule(p)) // _loop0_56 + (seq = _loop0_49_rule(p)) // _loop0_49 ) { - D(fprintf(stderr, "%*c+ _gather_55[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_56")); + D(fprintf(stderr, "%*c+ _gather_50[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_49")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_55[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_56")); + D(fprintf(stderr, "%*c%s _gather_50[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_49")); } _res = NULL; done: @@ -29164,9 +28593,9 @@ _gather_55_rule(Parser *p) return _res; } -// _loop0_58: ',' with_item +// _loop0_51: ',' keyword_pattern static asdl_seq * -_loop0_58_rule(Parser *p) +_loop0_51_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29186,18 +28615,18 @@ _loop0_58_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' with_item + { // ',' keyword_pattern if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c> _loop0_51[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); Token * _literal; - withitem_ty elem; + KeyPatternPair* elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = with_item_rule(p)) // with_item + (elem = keyword_pattern_rule(p)) // keyword_pattern ) { _res = elem; @@ -29223,8 +28652,8 @@ _loop0_58_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_58[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' with_item")); + D(fprintf(stderr, "%*c%s _loop0_51[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' keyword_pattern")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -29240,9 +28669,9 @@ _loop0_58_rule(Parser *p) return _seq; } -// _gather_57: with_item _loop0_58 +// _gather_52: keyword_pattern _loop0_51 static asdl_seq * -_gather_57_rule(Parser *p) +_gather_52_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29253,27 +28682,27 @@ _gather_57_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // with_item _loop0_58 + { // keyword_pattern _loop0_51 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "with_item _loop0_58")); - withitem_ty elem; + D(fprintf(stderr, "%*c> _gather_52[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_51")); + KeyPatternPair* elem; asdl_seq * seq; if ( - (elem = with_item_rule(p)) // with_item + (elem = keyword_pattern_rule(p)) // keyword_pattern && - (seq = _loop0_58_rule(p)) // _loop0_58 + (seq = _loop0_51_rule(p)) // _loop0_51 ) { - D(fprintf(stderr, "%*c+ _gather_57[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "with_item _loop0_58")); + D(fprintf(stderr, "%*c+ _gather_52[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_51")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_57[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "with_item _loop0_58")); + D(fprintf(stderr, "%*c%s _gather_52[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_51")); } _res = NULL; done: @@ -29281,9 +28710,9 @@ _gather_57_rule(Parser *p) return _res; } -// _tmp_59: ',' | ')' | ':' -static void * -_tmp_59_rule(Parser *p) +// _loop0_53: ',' type_param +static asdl_seq * +_loop0_53_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29292,64 +28721,105 @@ _tmp_59_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // ',' + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' type_param if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _loop0_53[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' type_param")); Token * _literal; - if ( + type_param_ty elem; + while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = type_param_rule(p)) // type_param ) { - D(fprintf(stderr, "%*c+ _tmp_59[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_59[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _loop0_53[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' type_param")); } - { // ')' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 8)) // token=')' - ) - { - D(fprintf(stderr, "%*c+ _tmp_59[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_59[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; } - { // ':' + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _gather_54: type_param _loop0_53 +static asdl_seq * +_gather_54_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // type_param _loop0_53 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; + D(fprintf(stderr, "%*c> _gather_54[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "type_param _loop0_53")); + type_param_ty elem; + asdl_seq * seq; if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' + (elem = type_param_rule(p)) // type_param + && + (seq = _loop0_53_rule(p)) // _loop0_53 ) { - D(fprintf(stderr, "%*c+ _tmp_59[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _gather_54[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "type_param _loop0_53")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_59[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c%s _gather_54[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "type_param _loop0_53")); } _res = NULL; done: @@ -29357,9 +28827,9 @@ _tmp_59_rule(Parser *p) return _res; } -// _loop1_60: except_block +// _loop1_55: (',' expression) static asdl_seq * -_loop1_60_rule(Parser *p) +_loop1_55_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29379,18 +28849,18 @@ _loop1_60_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // except_block + { // (',' expression) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); - excepthandler_ty except_block_var; + D(fprintf(stderr, "%*c> _loop1_55[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); + void *_tmp_17_var; while ( - (except_block_var = except_block_rule(p)) // except_block + (_tmp_17_var = _tmp_17_rule(p)) // ',' expression ) { - _res = except_block_var; + _res = _tmp_17_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29407,8 +28877,8 @@ _loop1_60_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_60[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); + D(fprintf(stderr, "%*c%s _loop1_55[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' expression)")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -29429,9 +28899,9 @@ _loop1_60_rule(Parser *p) return _seq; } -// _loop1_61: except_star_block +// _loop1_56: (',' star_expression) static asdl_seq * -_loop1_61_rule(Parser *p) +_loop1_56_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29451,18 +28921,18 @@ _loop1_61_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // except_star_block + { // (',' star_expression) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); - excepthandler_ty except_star_block_var; + D(fprintf(stderr, "%*c> _loop1_56[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); + void *_tmp_153_var; while ( - (except_star_block_var = except_star_block_rule(p)) // except_star_block + (_tmp_153_var = _tmp_153_rule(p)) // ',' star_expression ) { - _res = except_star_block_var; + _res = _tmp_153_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29479,8 +28949,8 @@ _loop1_61_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_61[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); + D(fprintf(stderr, "%*c%s _loop1_56[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_expression)")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -29501,9 +28971,9 @@ _loop1_61_rule(Parser *p) return _seq; } -// _tmp_62: 'as' NAME -static void * -_tmp_62_rule(Parser *p) +// _loop0_57: ',' star_named_expression +static asdl_seq * +_loop0_57_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29512,44 +28982,74 @@ _tmp_62_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // 'as' NAME + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' star_named_expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty z; - if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' + D(fprintf(stderr, "%*c> _loop0_57[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); + Token * _literal; + expr_ty elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (z = _PyPegen_name_token(p)) // NAME + (elem = star_named_expression_rule(p)) // star_named_expression ) { - D(fprintf(stderr, "%*c+ _tmp_62[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = z; + _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; + PyMem_Free(_children); p->level--; return NULL; } - goto done; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_62[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _loop0_57[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_named_expression")); } - _res = NULL; - done: + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); p->level--; - return _res; + return _seq; } -// _tmp_63: 'as' NAME -static void * -_tmp_63_rule(Parser *p) +// _gather_58: star_named_expression _loop0_57 +static asdl_seq * +_gather_58_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29558,34 +29058,29 @@ _tmp_63_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // star_named_expression _loop0_57 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty z; + D(fprintf(stderr, "%*c> _gather_58[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_57")); + expr_ty elem; + asdl_seq * seq; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' + (elem = star_named_expression_rule(p)) // star_named_expression && - (z = _PyPegen_name_token(p)) // NAME + (seq = _loop0_57_rule(p)) // _loop0_57 ) { - D(fprintf(stderr, "%*c+ _tmp_63[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = z; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _gather_58[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_57")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_63[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _gather_58[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_57")); } _res = NULL; done: @@ -29593,9 +29088,9 @@ _tmp_63_rule(Parser *p) return _res; } -// _loop1_64: case_block +// _loop1_59: ('or' conjunction) static asdl_seq * -_loop1_64_rule(Parser *p) +_loop1_59_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29615,18 +29110,18 @@ _loop1_64_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // case_block + { // ('or' conjunction) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "case_block")); - match_case_ty case_block_var; + D(fprintf(stderr, "%*c> _loop1_59[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); + void *_tmp_154_var; while ( - (case_block_var = case_block_rule(p)) // case_block + (_tmp_154_var = _tmp_154_rule(p)) // 'or' conjunction ) { - _res = case_block_var; + _res = _tmp_154_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29643,8 +29138,8 @@ _loop1_64_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_64[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "case_block")); + D(fprintf(stderr, "%*c%s _loop1_59[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('or' conjunction)")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -29665,9 +29160,9 @@ _loop1_64_rule(Parser *p) return _seq; } -// _loop0_66: '|' closed_pattern +// _loop1_60: ('and' inversion) static asdl_seq * -_loop0_66_rule(Parser *p) +_loop1_60_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29687,27 +29182,18 @@ _loop0_66_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // '|' closed_pattern + { // ('and' inversion) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'|' closed_pattern")); - Token * _literal; - pattern_ty elem; + D(fprintf(stderr, "%*c> _loop1_60[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); + void *_tmp_155_var; while ( - (_literal = _PyPegen_expect_token(p, 18)) // token='|' - && - (elem = closed_pattern_rule(p)) // closed_pattern + (_tmp_155_var = _tmp_155_rule(p)) // 'and' inversion ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } + _res = _tmp_155_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -29724,8 +29210,13 @@ _loop0_66_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_66[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'|' closed_pattern")); + D(fprintf(stderr, "%*c%s _loop1_60[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('and' inversion)")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -29741,9 +29232,9 @@ _loop0_66_rule(Parser *p) return _seq; } -// _gather_65: closed_pattern _loop0_66 +// _loop1_61: compare_op_bitwise_or_pair static asdl_seq * -_gather_65_rule(Parser *p) +_loop1_61_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29752,39 +29243,70 @@ _gather_65_rule(Parser *p) p->level--; return NULL; } - asdl_seq * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // closed_pattern _loop0_66 + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // compare_op_bitwise_or_pair if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_66")); - pattern_ty elem; - asdl_seq * seq; - if ( - (elem = closed_pattern_rule(p)) // closed_pattern - && - (seq = _loop0_66_rule(p)) // _loop0_66 + D(fprintf(stderr, "%*c> _loop1_61[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); + CmpopExprPair* compare_op_bitwise_or_pair_var; + while ( + (compare_op_bitwise_or_pair_var = compare_op_bitwise_or_pair_rule(p)) // compare_op_bitwise_or_pair ) { - D(fprintf(stderr, "%*c+ _gather_65[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "closed_pattern _loop0_66")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_65[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "closed_pattern _loop0_66")); - } - _res = NULL; - done: - p->level--; - return _res; + _res = compare_op_bitwise_or_pair_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop1_61[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "compare_op_bitwise_or_pair")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; } -// _tmp_67: '+' | '-' +// _tmp_62: '!=' static void * -_tmp_67_rule(Parser *p) +_tmp_62_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29795,43 +29317,29 @@ _tmp_67_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '+' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 14)) // token='+' - ) - { - D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); - } - { // '-' + { // '!=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_62[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); + Token * tok; if ( - (_literal = _PyPegen_expect_token(p, 15)) // token='-' + (tok = _PyPegen_expect_token(p, 28)) // token='!=' ) { - D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_62[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); + _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c%s _tmp_62[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!='")); } _res = NULL; done: @@ -29839,9 +29347,9 @@ _tmp_67_rule(Parser *p) return _res; } -// _tmp_68: '+' | '-' -static void * -_tmp_68_rule(Parser *p) +// _loop0_63: ',' (slice | starred_expression) +static asdl_seq * +_loop0_63_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29850,45 +29358,105 @@ _tmp_68_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // '+' + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' (slice | starred_expression) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c> _loop0_63[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (slice | starred_expression)")); Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 14)) // token='+' + void *elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = _tmp_156_rule(p)) // slice | starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); - _res = _literal; - goto done; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); + D(fprintf(stderr, "%*c%s _loop0_63[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (slice | starred_expression)")); } - { // '-' + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _gather_64: (slice | starred_expression) _loop0_63 +static asdl_seq * +_gather_64_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // (slice | starred_expression) _loop0_63 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); - Token * _literal; + D(fprintf(stderr, "%*c> _gather_64[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_63")); + void *elem; + asdl_seq * seq; if ( - (_literal = _PyPegen_expect_token(p, 15)) // token='-' + (elem = _tmp_156_rule(p)) // slice | starred_expression + && + (seq = _loop0_63_rule(p)) // _loop0_63 ) { - D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _gather_64[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_63")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c%s _gather_64[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(slice | starred_expression) _loop0_63")); } _res = NULL; done: @@ -29896,9 +29464,9 @@ _tmp_68_rule(Parser *p) return _res; } -// _tmp_69: '.' | '(' | '=' +// _tmp_65: ':' expression? static void * -_tmp_69_rule(Parser *p) +_tmp_65_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29909,62 +29477,89 @@ _tmp_69_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '.' + { // ':' expression? if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_65[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); Token * _literal; + void *d; if ( - (_literal = _PyPegen_expect_token(p, 23)) // token='.' + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + && + (d = expression_rule(p), !p->error_indicator) // expression? ) { - D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_65[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); + _res = d; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c%s _tmp_65[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression?")); } - { // '(' + _res = NULL; + done: + p->level--; + return _res; +} + +// _tmp_66: STRING | FSTRING_START +static void * +_tmp_66_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // STRING if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); + expr_ty string_var; if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' + (string_var = _PyPegen_string_token(p)) // STRING ) { - D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); + _res = string_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING")); } - { // '=' + { // FSTRING_START if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_66[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); + Token * fstring_start_var; if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' + (fstring_start_var = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' ) { - D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_66[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); + _res = fstring_start_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c%s _tmp_66[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_START")); } _res = NULL; done: @@ -29972,9 +29567,9 @@ _tmp_69_rule(Parser *p) return _res; } -// _tmp_70: '.' | '(' | '=' +// _tmp_67: tuple | group | genexp static void * -_tmp_70_rule(Parser *p) +_tmp_67_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -29985,62 +29580,62 @@ _tmp_70_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '.' + { // tuple if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + expr_ty tuple_var; if ( - (_literal = _PyPegen_expect_token(p, 23)) // token='.' + (tuple_var = tuple_rule(p)) // tuple ) { - D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + _res = tuple_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } - { // '(' + { // group if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); + expr_ty group_var; if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' + (group_var = group_rule(p)) // group ) { - D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); + _res = group_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "group")); } - { // '=' + { // genexp if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_67[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + expr_ty genexp_var; if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' + (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_67[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); + D(fprintf(stderr, "%*c%s _tmp_67[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } _res = NULL; done: @@ -30048,9 +29643,9 @@ _tmp_70_rule(Parser *p) return _res; } -// _loop0_72: ',' maybe_star_pattern -static asdl_seq * -_loop0_72_rule(Parser *p) +// _tmp_68: list | listcomp +static void * +_tmp_68_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30059,105 +29654,45 @@ _loop0_72_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' maybe_star_pattern + { // list if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' maybe_star_pattern")); - Token * _literal; - pattern_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = maybe_star_pattern_rule(p)) // maybe_star_pattern + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + expr_ty list_var; + if ( + (list_var = list_rule(p)) // list ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + _res = list_var; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_72[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' maybe_star_pattern")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_71: maybe_star_pattern _loop0_72 -static asdl_seq * -_gather_71_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // maybe_star_pattern _loop0_72 + { // listcomp if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_72")); - pattern_ty elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); + expr_ty listcomp_var; if ( - (elem = maybe_star_pattern_rule(p)) // maybe_star_pattern - && - (seq = _loop0_72_rule(p)) // _loop0_72 + (listcomp_var = listcomp_rule(p)) // listcomp ) { - D(fprintf(stderr, "%*c+ _gather_71[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "maybe_star_pattern _loop0_72")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_68[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); + _res = listcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_71[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "maybe_star_pattern _loop0_72")); + D(fprintf(stderr, "%*c%s _tmp_68[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "listcomp")); } _res = NULL; done: @@ -30165,9 +29700,9 @@ _gather_71_rule(Parser *p) return _res; } -// _loop0_74: ',' key_value_pattern -static asdl_seq * -_loop0_74_rule(Parser *p) +// _tmp_69: dict | set | dictcomp | setcomp +static void * +_tmp_69_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30176,105 +29711,83 @@ _loop0_74_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' key_value_pattern + { // dict if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' key_value_pattern")); - Token * _literal; - KeyPatternPair* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = key_value_pattern_rule(p)) // key_value_pattern + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); + expr_ty dict_var; + if ( + (dict_var = dict_rule(p)) // dict ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); + _res = dict_var; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_74[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' key_value_pattern")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dict")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_73: key_value_pattern _loop0_74 -static asdl_seq * -_gather_73_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); + { // set + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); + expr_ty set_var; + if ( + (set_var = set_rule(p)) // set + ) + { + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); + _res = set_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "set")); } - if (p->error_indicator) { - p->level--; - return NULL; + { // dictcomp + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); + expr_ty dictcomp_var; + if ( + (dictcomp_var = dictcomp_rule(p)) // dictcomp + ) + { + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); + _res = dictcomp_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dictcomp")); } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // key_value_pattern _loop0_74 + { // setcomp if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_74")); - KeyPatternPair* elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_69[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); + expr_ty setcomp_var; if ( - (elem = key_value_pattern_rule(p)) // key_value_pattern - && - (seq = _loop0_74_rule(p)) // _loop0_74 + (setcomp_var = setcomp_rule(p)) // setcomp ) { - D(fprintf(stderr, "%*c+ _gather_73[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "key_value_pattern _loop0_74")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_69[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); + _res = setcomp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_73[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "key_value_pattern _loop0_74")); + D(fprintf(stderr, "%*c%s _tmp_69[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "setcomp")); } _res = NULL; done: @@ -30282,9 +29795,9 @@ _gather_73_rule(Parser *p) return _res; } -// _tmp_75: literal_expr | attr +// _tmp_70: yield_expr | named_expression static void * -_tmp_75_rule(Parser *p) +_tmp_70_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30295,43 +29808,43 @@ _tmp_75_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // literal_expr + { // yield_expr if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "literal_expr")); - expr_ty literal_expr_var; + D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + expr_ty yield_expr_var; if ( - (literal_expr_var = literal_expr_rule(p)) // literal_expr + (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_75[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "literal_expr")); - _res = literal_expr_var; + D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_75[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "literal_expr")); + D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } - { // attr + { // named_expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "attr")); - expr_ty attr_var; + D(fprintf(stderr, "%*c> _tmp_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); + expr_ty named_expression_var; if ( - (attr_var = attr_rule(p)) // attr + (named_expression_var = named_expression_rule(p)) // named_expression ) { - D(fprintf(stderr, "%*c+ _tmp_75[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "attr")); - _res = attr_var; + D(fprintf(stderr, "%*c+ _tmp_70[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); + _res = named_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_75[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "attr")); + D(fprintf(stderr, "%*c%s _tmp_70[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression")); } _res = NULL; done: @@ -30339,9 +29852,9 @@ _tmp_75_rule(Parser *p) return _res; } -// _loop0_77: ',' pattern +// _loop0_71: lambda_param_no_default static asdl_seq * -_loop0_77_rule(Parser *p) +_loop0_71_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30361,27 +29874,18 @@ _loop0_77_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' pattern + { // lambda_param_no_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' pattern")); - Token * _literal; - pattern_ty elem; + D(fprintf(stderr, "%*c> _loop0_71[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + arg_ty lambda_param_no_default_var; while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = pattern_rule(p)) // pattern + (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } + _res = lambda_param_no_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30398,8 +29902,8 @@ _loop0_77_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_77[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' pattern")); + D(fprintf(stderr, "%*c%s _loop0_71[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -30415,9 +29919,9 @@ _loop0_77_rule(Parser *p) return _seq; } -// _gather_76: pattern _loop0_77 +// _loop0_72: lambda_param_with_default static asdl_seq * -_gather_76_rule(Parser *p) +_loop0_72_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30426,48 +29930,7 @@ _gather_76_rule(Parser *p) p->level--; return NULL; } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // pattern _loop0_77 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "pattern _loop0_77")); - pattern_ty elem; - asdl_seq * seq; - if ( - (elem = pattern_rule(p)) // pattern - && - (seq = _loop0_77_rule(p)) // _loop0_77 - ) - { - D(fprintf(stderr, "%*c+ _gather_76[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "pattern _loop0_77")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_76[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "pattern _loop0_77")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_79: ',' keyword_pattern -static asdl_seq * -_loop0_79_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; + void *_res = NULL; int _mark = p->mark; void **_children = PyMem_Malloc(sizeof(void *)); if (!_children) { @@ -30478,27 +29941,18 @@ _loop0_79_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' keyword_pattern + { // lambda_param_with_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' keyword_pattern")); - Token * _literal; - KeyPatternPair* elem; + D(fprintf(stderr, "%*c> _loop0_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + NameDefaultPair* lambda_param_with_default_var; while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = keyword_pattern_rule(p)) // keyword_pattern + (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } + _res = lambda_param_with_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30515,8 +29969,8 @@ _loop0_79_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_79[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' keyword_pattern")); + D(fprintf(stderr, "%*c%s _loop0_72[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -30532,50 +29986,9 @@ _loop0_79_rule(Parser *p) return _seq; } -// _gather_78: keyword_pattern _loop0_79 +// _loop1_73: lambda_param_no_default static asdl_seq * -_gather_78_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // keyword_pattern _loop0_79 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_79")); - KeyPatternPair* elem; - asdl_seq * seq; - if ( - (elem = keyword_pattern_rule(p)) // keyword_pattern - && - (seq = _loop0_79_rule(p)) // _loop0_79 - ) - { - D(fprintf(stderr, "%*c+ _gather_78[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "keyword_pattern _loop0_79")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_78[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "keyword_pattern _loop0_79")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_81: ',' type_param -static asdl_seq * -_loop0_81_rule(Parser *p) +_loop1_73_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30595,27 +30008,18 @@ _loop0_81_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' type_param + { // lambda_param_no_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' type_param")); - Token * _literal; - type_param_ty elem; + D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + arg_ty lambda_param_no_default_var; while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = type_param_rule(p)) // type_param + (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } + _res = lambda_param_no_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30632,8 +30036,13 @@ _loop0_81_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_81[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' type_param")); + D(fprintf(stderr, "%*c%s _loop1_73[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -30649,50 +30058,9 @@ _loop0_81_rule(Parser *p) return _seq; } -// _gather_80: type_param _loop0_81 +// _loop1_74: lambda_param_with_default static asdl_seq * -_gather_80_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // type_param _loop0_81 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "type_param _loop0_81")); - type_param_ty elem; - asdl_seq * seq; - if ( - (elem = type_param_rule(p)) // type_param - && - (seq = _loop0_81_rule(p)) // _loop0_81 - ) - { - D(fprintf(stderr, "%*c+ _gather_80[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "type_param _loop0_81")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_80[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "type_param _loop0_81")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_82: (',' expression) -static asdl_seq * -_loop1_82_rule(Parser *p) +_loop1_74_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30712,18 +30080,18 @@ _loop1_82_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // (',' expression) + { // lambda_param_with_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_251_var; + D(fprintf(stderr, "%*c> _loop1_74[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + NameDefaultPair* lambda_param_with_default_var; while ( - (_tmp_251_var = _tmp_251_rule(p)) // ',' expression + (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default ) { - _res = _tmp_251_var; + _res = lambda_param_with_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30740,8 +30108,8 @@ _loop1_82_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_82[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' expression)")); + D(fprintf(stderr, "%*c%s _loop1_74[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -30762,9 +30130,9 @@ _loop1_82_rule(Parser *p) return _seq; } -// _loop1_83: (',' star_expression) +// _loop0_75: lambda_param_maybe_default static asdl_seq * -_loop1_83_rule(Parser *p) +_loop0_75_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30784,18 +30152,18 @@ _loop1_83_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // (',' star_expression) + { // lambda_param_maybe_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_252_var; + D(fprintf(stderr, "%*c> _loop0_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + NameDefaultPair* lambda_param_maybe_default_var; while ( - (_tmp_252_var = _tmp_252_rule(p)) // ',' star_expression + (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default ) { - _res = _tmp_252_var; + _res = lambda_param_maybe_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30812,13 +30180,8 @@ _loop1_83_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_expression)")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_75[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -30834,9 +30197,9 @@ _loop1_83_rule(Parser *p) return _seq; } -// _loop0_85: ',' star_named_expression +// _loop1_76: lambda_param_maybe_default static asdl_seq * -_loop0_85_rule(Parser *p) +_loop1_76_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30856,27 +30219,18 @@ _loop0_85_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' star_named_expression + { // lambda_param_maybe_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_named_expression")); - Token * _literal; - expr_ty elem; + D(fprintf(stderr, "%*c> _loop1_76[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); + NameDefaultPair* lambda_param_maybe_default_var; while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = star_named_expression_rule(p)) // star_named_expression + (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } + _res = lambda_param_maybe_default_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -30893,8 +30247,13 @@ _loop0_85_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_85[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_named_expression")); + D(fprintf(stderr, "%*c%s _loop1_76[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); + } + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -30910,50 +30269,9 @@ _loop0_85_rule(Parser *p) return _seq; } -// _gather_84: star_named_expression _loop0_85 -static asdl_seq * -_gather_84_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // star_named_expression _loop0_85 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_85")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = star_named_expression_rule(p)) // star_named_expression - && - (seq = _loop0_85_rule(p)) // _loop0_85 - ) - { - D(fprintf(stderr, "%*c+ _gather_84[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression _loop0_85")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_84[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression _loop0_85")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_86: ('or' conjunction) +// _loop0_77: fstring_format_spec static asdl_seq * -_loop1_86_rule(Parser *p) +_loop0_77_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -30973,18 +30291,18 @@ _loop1_86_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ('or' conjunction) + { // fstring_format_spec if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_253_var; + D(fprintf(stderr, "%*c> _loop0_77[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); + expr_ty fstring_format_spec_var; while ( - (_tmp_253_var = _tmp_253_rule(p)) // 'or' conjunction + (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec ) { - _res = _tmp_253_var; + _res = fstring_format_spec_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31001,13 +30319,8 @@ _loop1_86_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_86[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('or' conjunction)")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_77[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31023,9 +30336,9 @@ _loop1_86_rule(Parser *p) return _seq; } -// _loop1_87: ('and' inversion) +// _loop0_78: fstring_middle static asdl_seq * -_loop1_87_rule(Parser *p) +_loop0_78_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31045,18 +30358,18 @@ _loop1_87_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ('and' inversion) + { // fstring_middle if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_254_var; + D(fprintf(stderr, "%*c> _loop0_78[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_middle")); + expr_ty fstring_middle_var; while ( - (_tmp_254_var = _tmp_254_rule(p)) // 'and' inversion + (fstring_middle_var = fstring_middle_rule(p)) // fstring_middle ) { - _res = _tmp_254_var; + _res = fstring_middle_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31073,13 +30386,8 @@ _loop1_87_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_87[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('and' inversion)")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_78[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_middle")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31095,9 +30403,9 @@ _loop1_87_rule(Parser *p) return _seq; } -// _loop1_88: compare_op_bitwise_or_pair +// _loop1_79: (fstring | string) static asdl_seq * -_loop1_88_rule(Parser *p) +_loop1_79_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31117,18 +30425,18 @@ _loop1_88_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // compare_op_bitwise_or_pair + { // (fstring | string) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "compare_op_bitwise_or_pair")); - CmpopExprPair* compare_op_bitwise_or_pair_var; + D(fprintf(stderr, "%*c> _loop1_79[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); + void *_tmp_157_var; while ( - (compare_op_bitwise_or_pair_var = compare_op_bitwise_or_pair_rule(p)) // compare_op_bitwise_or_pair + (_tmp_157_var = _tmp_157_rule(p)) // fstring | string ) { - _res = compare_op_bitwise_or_pair_var; + _res = _tmp_157_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31145,8 +30453,8 @@ _loop1_88_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_88[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "compare_op_bitwise_or_pair")); + D(fprintf(stderr, "%*c%s _loop1_79[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(fstring | string)")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -31167,9 +30475,9 @@ _loop1_88_rule(Parser *p) return _seq; } -// _tmp_89: '!=' +// _tmp_80: star_named_expression ',' star_named_expressions? static void * -_tmp_89_rule(Parser *p) +_tmp_80_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31180,19 +30488,25 @@ _tmp_89_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '!=' + { // star_named_expression ',' star_named_expressions? if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!='")); - Token * tok; + D(fprintf(stderr, "%*c> _tmp_80[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + Token * _literal; + expr_ty y; + void *z; if ( - (tok = _PyPegen_expect_token(p, 28)) // token='!=' + (y = star_named_expression_rule(p)) // star_named_expression + && + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (z = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? ) { - D(fprintf(stderr, "%*c+ _tmp_89[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='")); - _res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok; + D(fprintf(stderr, "%*c+ _tmp_80[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); + _res = _PyPegen_seq_insert_in_front ( p , y , z ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -31201,8 +30515,8 @@ _tmp_89_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_89[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!='")); + D(fprintf(stderr, "%*c%s _tmp_80[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression ',' star_named_expressions?")); } _res = NULL; done: @@ -31210,9 +30524,9 @@ _tmp_89_rule(Parser *p) return _res; } -// _loop0_91: ',' (slice | starred_expression) +// _loop0_81: ',' double_starred_kvpair static asdl_seq * -_loop0_91_rule(Parser *p) +_loop0_81_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31232,18 +30546,18 @@ _loop0_91_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' (slice | starred_expression) + { // ',' double_starred_kvpair if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (slice | starred_expression)")); + D(fprintf(stderr, "%*c> _loop0_81[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); Token * _literal; - void *elem; + KeyValuePair* elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = _tmp_255_rule(p)) // slice | starred_expression + (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair ) { _res = elem; @@ -31269,8 +30583,8 @@ _loop0_91_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_91[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (slice | starred_expression)")); + D(fprintf(stderr, "%*c%s _loop0_81[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31286,9 +30600,9 @@ _loop0_91_rule(Parser *p) return _seq; } -// _gather_90: (slice | starred_expression) _loop0_91 +// _gather_82: double_starred_kvpair _loop0_81 static asdl_seq * -_gather_90_rule(Parser *p) +_gather_82_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31299,27 +30613,27 @@ _gather_90_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // (slice | starred_expression) _loop0_91 + { // double_starred_kvpair _loop0_81 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_91")); - void *elem; + D(fprintf(stderr, "%*c> _gather_82[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_81")); + KeyValuePair* elem; asdl_seq * seq; if ( - (elem = _tmp_255_rule(p)) // slice | starred_expression + (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair && - (seq = _loop0_91_rule(p)) // _loop0_91 + (seq = _loop0_81_rule(p)) // _loop0_81 ) { - D(fprintf(stderr, "%*c+ _gather_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(slice | starred_expression) _loop0_91")); + D(fprintf(stderr, "%*c+ _gather_82[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_81")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_90[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(slice | starred_expression) _loop0_91")); + D(fprintf(stderr, "%*c%s _gather_82[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_81")); } _res = NULL; done: @@ -31327,9 +30641,9 @@ _gather_90_rule(Parser *p) return _res; } -// _tmp_92: ':' expression? -static void * -_tmp_92_rule(Parser *p) +// _loop1_83: for_if_clause +static asdl_seq * +_loop1_83_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31338,44 +30652,70 @@ _tmp_92_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // ':' expression? + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // for_if_clause if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':' expression?")); - Token * _literal; - void *d; - if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' - && - (d = expression_rule(p), !p->error_indicator) // expression? + D(fprintf(stderr, "%*c> _loop1_83[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); + comprehension_ty for_if_clause_var; + while ( + (for_if_clause_var = for_if_clause_rule(p)) // for_if_clause ) { - D(fprintf(stderr, "%*c+ _tmp_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':' expression?")); - _res = d; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; + _res = for_if_clause_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; } - goto done; + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_92[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':' expression?")); + D(fprintf(stderr, "%*c%s _loop1_83[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause")); } - _res = NULL; - done: + if (_n == 0 || p->error_indicator) { + PyMem_Free(_children); + p->level--; + return NULL; + } + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); p->level--; - return _res; + return _seq; } -// _tmp_93: STRING | FSTRING_START -static void * -_tmp_93_rule(Parser *p) +// _loop0_84: ('if' disjunction) +static asdl_seq * +_loop0_84_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31384,55 +30724,65 @@ _tmp_93_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // STRING - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "STRING")); - expr_ty string_var; - if ( - (string_var = _PyPegen_string_token(p)) // STRING - ) - { - D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "STRING")); - _res = string_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "STRING")); + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; } - { // FSTRING_START + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ('if' disjunction) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); - Token * fstring_start_var; - if ( - (fstring_start_var = _PyPegen_expect_token(p, FSTRING_START)) // token='FSTRING_START' + D(fprintf(stderr, "%*c> _loop0_84[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); + void *_tmp_158_var; + while ( + (_tmp_158_var = _tmp_158_rule(p)) // 'if' disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "FSTRING_START")); - _res = fstring_start_var; - goto done; + _res = _tmp_158_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_93[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "FSTRING_START")); + D(fprintf(stderr, "%*c%s _loop0_84[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); } - _res = NULL; - done: + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); p->level--; - return _res; + return _seq; } -// _tmp_94: tuple | group | genexp +// _tmp_85: assignment_expression | expression !':=' static void * -_tmp_94_rule(Parser *p) +_tmp_85_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31443,62 +30793,45 @@ _tmp_94_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // tuple - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); - expr_ty tuple_var; - if ( - (tuple_var = tuple_rule(p)) // tuple - ) - { - D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); - _res = tuple_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); - } - { // group + { // assignment_expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "group")); - expr_ty group_var; + D(fprintf(stderr, "%*c> _tmp_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + expr_ty assignment_expression_var; if ( - (group_var = group_rule(p)) // group + (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression ) { - D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "group")); - _res = group_var; + D(fprintf(stderr, "%*c+ _tmp_85[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); + _res = assignment_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "group")); + D(fprintf(stderr, "%*c%s _tmp_85[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); } - { // genexp + { // expression !':=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); - expr_ty genexp_var; + D(fprintf(stderr, "%*c> _tmp_85[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + expr_ty expression_var; if ( - (genexp_var = genexp_rule(p)) // genexp + (expression_var = expression_rule(p)) // expression + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' ) { - D(fprintf(stderr, "%*c+ _tmp_94[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); - _res = genexp_var; + D(fprintf(stderr, "%*c+ _tmp_85[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); + _res = expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_94[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); + D(fprintf(stderr, "%*c%s _tmp_85[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); } _res = NULL; done: @@ -31506,9 +30839,9 @@ _tmp_94_rule(Parser *p) return _res; } -// _tmp_95: list | listcomp -static void * -_tmp_95_rule(Parser *p) +// _loop0_86: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +static asdl_seq * +_loop0_86_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31517,55 +30850,75 @@ _tmp_95_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // list - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); - expr_ty list_var; - if ( - (list_var = list_rule(p)) // list - ) - { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); - _res = list_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; } - { // listcomp + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "listcomp")); - expr_ty listcomp_var; - if ( - (listcomp_var = listcomp_rule(p)) // listcomp + D(fprintf(stderr, "%*c> _loop0_86[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + Token * _literal; + void *elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = _tmp_159_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' ) { - D(fprintf(stderr, "%*c+ _tmp_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "listcomp")); - _res = listcomp_var; - goto done; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_95[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "listcomp")); + D(fprintf(stderr, "%*c%s _loop0_86[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); } - _res = NULL; - done: + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); p->level--; - return _res; + return _seq; } -// _tmp_96: dict | set | dictcomp | setcomp -static void * -_tmp_96_rule(Parser *p) +// _gather_87: +// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_86 +static asdl_seq * +_gather_87_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31574,83 +30927,29 @@ _tmp_96_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - { // dict - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dict")); - expr_ty dict_var; - if ( - (dict_var = dict_rule(p)) // dict - ) - { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dict")); - _res = dict_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dict")); - } - { // set - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "set")); - expr_ty set_var; - if ( - (set_var = set_rule(p)) // set - ) - { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "set")); - _res = set_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "set")); - } - { // dictcomp - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dictcomp")); - expr_ty dictcomp_var; - if ( - (dictcomp_var = dictcomp_rule(p)) // dictcomp - ) - { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dictcomp")); - _res = dictcomp_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dictcomp")); - } - { // setcomp + { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_86 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "setcomp")); - expr_ty setcomp_var; + D(fprintf(stderr, "%*c> _gather_87[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_86")); + void *elem; + asdl_seq * seq; if ( - (setcomp_var = setcomp_rule(p)) // setcomp + (elem = _tmp_159_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + && + (seq = _loop0_86_rule(p)) // _loop0_86 ) { - D(fprintf(stderr, "%*c+ _tmp_96[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "setcomp")); - _res = setcomp_var; + D(fprintf(stderr, "%*c+ _gather_87[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_86")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_96[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "setcomp")); + D(fprintf(stderr, "%*c%s _gather_87[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_86")); } _res = NULL; done: @@ -31658,9 +30957,9 @@ _tmp_96_rule(Parser *p) return _res; } -// _tmp_97: yield_expr | named_expression +// _tmp_88: ',' kwargs static void * -_tmp_97_rule(Parser *p) +_tmp_88_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31671,43 +30970,32 @@ _tmp_97_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // yield_expr - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); - expr_ty yield_expr_var; - if ( - (yield_expr_var = yield_expr_rule(p)) // yield_expr - ) - { - D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); - _res = yield_expr_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); - } - { // named_expression + { // ',' kwargs if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression")); - expr_ty named_expression_var; + D(fprintf(stderr, "%*c> _tmp_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + Token * _literal; + asdl_seq* k; if ( - (named_expression_var = named_expression_rule(p)) // named_expression + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression")); - _res = named_expression_var; + D(fprintf(stderr, "%*c+ _tmp_88[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + _res = k; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression")); + D(fprintf(stderr, "%*c%s _tmp_88[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; done: @@ -31715,9 +31003,9 @@ _tmp_97_rule(Parser *p) return _res; } -// _loop0_98: lambda_param_no_default +// _loop0_89: ',' kwarg_or_starred static asdl_seq * -_loop0_98_rule(Parser *p) +_loop0_89_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31737,18 +31025,27 @@ _loop0_98_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_no_default + { // ',' kwarg_or_starred if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; + D(fprintf(stderr, "%*c> _loop0_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + Token * _literal; + KeywordOrStarred* elem; while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred ) { - _res = lambda_param_no_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31765,8 +31062,8 @@ _loop0_98_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_98[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c%s _loop0_89[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31782,9 +31079,50 @@ _loop0_98_rule(Parser *p) return _seq; } -// _loop0_99: lambda_param_with_default +// _gather_90: kwarg_or_starred _loop0_89 +static asdl_seq * +_gather_90_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // kwarg_or_starred _loop0_89 + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _gather_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_89")); + KeywordOrStarred* elem; + asdl_seq * seq; + if ( + (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred + && + (seq = _loop0_89_rule(p)) // _loop0_89 + ) + { + D(fprintf(stderr, "%*c+ _gather_90[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_89")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_90[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_89")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _loop0_91: ',' kwarg_or_double_starred static asdl_seq * -_loop0_99_rule(Parser *p) +_loop0_91_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31804,18 +31142,27 @@ _loop0_99_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_with_default + { // ',' kwarg_or_double_starred if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; + D(fprintf(stderr, "%*c> _loop0_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + Token * _literal; + KeywordOrStarred* elem; while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred ) { - _res = lambda_param_with_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31832,8 +31179,8 @@ _loop0_99_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_99[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c%s _loop0_91[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31849,9 +31196,50 @@ _loop0_99_rule(Parser *p) return _seq; } -// _loop0_100: lambda_param_with_default +// _gather_92: kwarg_or_double_starred _loop0_91 static asdl_seq * -_loop0_100_rule(Parser *p) +_gather_92_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); + } + if (p->error_indicator) { + p->level--; + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // kwarg_or_double_starred _loop0_91 + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _gather_92[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_91")); + KeywordOrStarred* elem; + asdl_seq * seq; + if ( + (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred + && + (seq = _loop0_91_rule(p)) // _loop0_91 + ) + { + D(fprintf(stderr, "%*c+ _gather_92[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_91")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _gather_92[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_91")); + } + _res = NULL; + done: + p->level--; + return _res; +} + +// _loop0_93: (',' star_target) +static asdl_seq * +_loop0_93_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31871,18 +31259,18 @@ _loop0_100_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_with_default + { // (',' star_target) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; + D(fprintf(stderr, "%*c> _loop0_93[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_160_var; while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default + (_tmp_160_var = _tmp_160_rule(p)) // ',' star_target ) { - _res = lambda_param_with_default_var; + _res = _tmp_160_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31899,8 +31287,8 @@ _loop0_100_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_100[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c%s _loop0_93[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31916,9 +31304,9 @@ _loop0_100_rule(Parser *p) return _seq; } -// _loop1_101: lambda_param_no_default +// _loop0_94: ',' star_target static asdl_seq * -_loop1_101_rule(Parser *p) +_loop0_94_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31938,18 +31326,27 @@ _loop1_101_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_no_default + { // ',' star_target if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; + D(fprintf(stderr, "%*c> _loop0_94[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + Token * _literal; + expr_ty elem; while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = star_target_rule(p)) // star_target ) { - _res = lambda_param_no_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -31966,13 +31363,8 @@ _loop1_101_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_101[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_94[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -31988,9 +31380,9 @@ _loop1_101_rule(Parser *p) return _seq; } -// _loop0_102: lambda_param_with_default +// _gather_95: star_target _loop0_94 static asdl_seq * -_loop0_102_rule(Parser *p) +_gather_95_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -31999,65 +31391,39 @@ _loop0_102_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_with_default + { // star_target _loop0_94 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; - while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default + D(fprintf(stderr, "%*c> _gather_95[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_94")); + expr_ty elem; + asdl_seq * seq; + if ( + (elem = star_target_rule(p)) // star_target + && + (seq = _loop0_94_rule(p)) // _loop0_94 ) { - _res = lambda_param_with_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _gather_95[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_94")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_102[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _gather_95[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_94")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop1_103: lambda_param_with_default +// _loop1_96: (',' star_target) static asdl_seq * -_loop1_103_rule(Parser *p) +_loop1_96_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32077,18 +31443,18 @@ _loop1_103_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_with_default + { // (',' star_target) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; + D(fprintf(stderr, "%*c> _loop1_96[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_160_var; while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default + (_tmp_160_var = _tmp_160_rule(p)) // ',' star_target ) { - _res = lambda_param_with_default_var; + _res = _tmp_160_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32105,8 +31471,8 @@ _loop1_103_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_103[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c%s _loop1_96[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } if (_n == 0 || p->error_indicator) { PyMem_Free(_children); @@ -32127,9 +31493,9 @@ _loop1_103_rule(Parser *p) return _seq; } -// _loop1_104: lambda_param_no_default -static asdl_seq * -_loop1_104_rule(Parser *p) +// _tmp_97: !'*' star_target +static void * +_tmp_97_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32138,70 +31504,38 @@ _loop1_104_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_no_default + { // !'*' star_target if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + D(fprintf(stderr, "%*c> _tmp_97[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + expr_ty star_target_var; + if ( + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' + && + (star_target_var = star_target_rule(p)) // star_target ) { - _res = lambda_param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_97[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + _res = star_target_var; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_104[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_97[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop1_105: lambda_param_no_default +// _loop0_98: ',' del_target static asdl_seq * -_loop1_105_rule(Parser *p) +_loop0_98_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32221,18 +31555,27 @@ _loop1_105_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_no_default + { // ',' del_target if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; + D(fprintf(stderr, "%*c> _loop0_98[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); + Token * _literal; + expr_ty elem; while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = del_target_rule(p)) // del_target ) { - _res = lambda_param_no_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32249,13 +31592,8 @@ _loop1_105_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_105[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_98[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -32271,9 +31609,9 @@ _loop1_105_rule(Parser *p) return _seq; } -// _loop0_106: lambda_param_no_default +// _gather_99: del_target _loop0_98 static asdl_seq * -_loop0_106_rule(Parser *p) +_gather_99_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32282,65 +31620,39 @@ _loop0_106_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_no_default + { // del_target _loop0_98 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + D(fprintf(stderr, "%*c> _gather_99[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_98")); + expr_ty elem; + asdl_seq * seq; + if ( + (elem = del_target_rule(p)) // del_target + && + (seq = _loop0_98_rule(p)) // _loop0_98 ) { - _res = lambda_param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _gather_99[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_98")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_106[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _gather_99[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_98")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop1_107: lambda_param_with_default +// _loop0_100: ',' expression static asdl_seq * -_loop1_107_rule(Parser *p) +_loop0_100_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32360,18 +31672,27 @@ _loop1_107_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_with_default + { // ',' expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; + D(fprintf(stderr, "%*c> _loop0_100[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + Token * _literal; + expr_ty elem; while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = expression_rule(p)) // expression ) { - _res = lambda_param_with_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32388,13 +31709,8 @@ _loop1_107_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_107[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_100[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -32410,9 +31726,9 @@ _loop1_107_rule(Parser *p) return _seq; } -// _loop0_108: lambda_param_no_default +// _gather_101: expression _loop0_100 static asdl_seq * -_loop0_108_rule(Parser *p) +_gather_101_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32421,65 +31737,39 @@ _loop0_108_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_no_default + { // expression _loop0_100 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default + D(fprintf(stderr, "%*c> _gather_101[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_100")); + expr_ty elem; + asdl_seq * seq; + if ( + (elem = expression_rule(p)) // expression + && + (seq = _loop0_100_rule(p)) // _loop0_100 ) { - _res = lambda_param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _gather_101[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_100")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_108[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _gather_101[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_100")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop1_109: lambda_param_with_default -static asdl_seq * -_loop1_109_rule(Parser *p) +// _tmp_102: NEWLINE INDENT +static void * +_tmp_102_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32488,70 +31778,41 @@ _loop1_109_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_with_default + { // NEWLINE INDENT if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; - while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default + D(fprintf(stderr, "%*c> _tmp_102[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + Token * indent_var; + Token * newline_var; + if ( + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + && + (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' ) { - _res = lambda_param_with_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_102[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); + _res = _PyPegen_dummy_name(p, newline_var, indent_var); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_109[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_102[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE INDENT")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop0_110: lambda_param_maybe_default -static asdl_seq * -_loop0_110_rule(Parser *p) +// _tmp_103: +// | (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) +// | kwargs +static void * +_tmp_103_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32560,65 +31821,55 @@ _loop0_110_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_maybe_default + { // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; - while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default + D(fprintf(stderr, "%*c> _tmp_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + void *_tmp_161_var; + if ( + (_tmp_161_var = _tmp_161_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs ) { - _res = lambda_param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_103[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); + _res = _tmp_161_var; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_110[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); + D(fprintf(stderr, "%*c%s _tmp_103[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + { // kwargs + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_103[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); + asdl_seq* kwargs_var; + if ( + (kwargs_var = kwargs_rule(p)) // kwargs + ) + { + D(fprintf(stderr, "%*c+ _tmp_103[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); + _res = kwargs_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_103[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwargs")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop1_111: lambda_param_maybe_default +// _loop0_104: ',' (starred_expression !'=') static asdl_seq * -_loop1_111_rule(Parser *p) +_loop0_104_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32638,18 +31889,27 @@ _loop1_111_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // lambda_param_maybe_default + { // ',' (starred_expression !'=') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; + D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression !'=')")); + Token * _literal; + void *elem; while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = _tmp_162_rule(p)) // starred_expression !'=' ) { - _res = lambda_param_maybe_default_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -32666,13 +31926,8 @@ _loop1_111_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_111[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_104[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression !'=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -32688,9 +31943,9 @@ _loop1_111_rule(Parser *p) return _seq; } -// _loop0_112: fstring_format_spec +// _gather_105: (starred_expression !'=') _loop0_104 static asdl_seq * -_loop0_112_rule(Parser *p) +_gather_105_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32699,65 +31954,39 @@ _loop0_112_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // fstring_format_spec + { // (starred_expression !'=') _loop0_104 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); - expr_ty fstring_format_spec_var; - while ( - (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec + D(fprintf(stderr, "%*c> _gather_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_104")); + void *elem; + asdl_seq * seq; + if ( + (elem = _tmp_162_rule(p)) // starred_expression !'=' + && + (seq = _loop0_104_rule(p)) // _loop0_104 ) { - _res = fstring_format_spec_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _gather_105[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_104")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _gather_105[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression !'=') _loop0_104")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _loop0_113: fstring_middle -static asdl_seq * -_loop0_113_rule(Parser *p) +// _tmp_106: args | expression for_if_clauses +static void * +_tmp_106_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -32766,5375 +31995,58 @@ _loop0_113_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // fstring_middle + { // args if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_middle")); - expr_ty fstring_middle_var; - while ( - (fstring_middle_var = fstring_middle_rule(p)) // fstring_middle + D(fprintf(stderr, "%*c> _tmp_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); + expr_ty args_var; + if ( + (args_var = args_rule(p)) // args ) { - _res = fstring_middle_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_106[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + _res = args_var; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_113[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_middle")); + D(fprintf(stderr, "%*c%s _tmp_106[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_114: (fstring | string) -static asdl_seq * -_loop1_114_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (fstring | string) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(fstring | string)")); - void *_tmp_256_var; - while ( - (_tmp_256_var = _tmp_256_rule(p)) // fstring | string - ) - { - _res = _tmp_256_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_114[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(fstring | string)")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_115: star_named_expression ',' star_named_expressions? -static void * -_tmp_115_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // star_named_expression ',' star_named_expressions? - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); - Token * _literal; - expr_ty y; - void *z; - if ( - (y = star_named_expression_rule(p)) // star_named_expression - && - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (z = star_named_expressions_rule(p), !p->error_indicator) // star_named_expressions? - ) - { - D(fprintf(stderr, "%*c+ _tmp_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions?")); - _res = _PyPegen_seq_insert_in_front ( p , y , z ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_115[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expression ',' star_named_expressions?")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_117: ',' double_starred_kvpair -static asdl_seq * -_loop0_117_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' double_starred_kvpair - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); - Token * _literal; - KeyValuePair* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_117[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_116: double_starred_kvpair _loop0_117 -static asdl_seq * -_gather_116_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // double_starred_kvpair _loop0_117 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_117")); - KeyValuePair* elem; - asdl_seq * seq; - if ( - (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair - && - (seq = _loop0_117_rule(p)) // _loop0_117 - ) - { - D(fprintf(stderr, "%*c+ _gather_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_117")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_116[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_117")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_118: for_if_clause -static asdl_seq * -_loop1_118_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // for_if_clause - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "for_if_clause")); - comprehension_ty for_if_clause_var; - while ( - (for_if_clause_var = for_if_clause_rule(p)) // for_if_clause - ) - { - _res = for_if_clause_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_118[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "for_if_clause")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_119: ('if' disjunction) -static asdl_seq * -_loop0_119_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ('if' disjunction) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_257_var; - while ( - (_tmp_257_var = _tmp_257_rule(p)) // 'if' disjunction - ) - { - _res = _tmp_257_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_120: ('if' disjunction) -static asdl_seq * -_loop0_120_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ('if' disjunction) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_258_var; - while ( - (_tmp_258_var = _tmp_258_rule(p)) // 'if' disjunction - ) - { - _res = _tmp_258_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "('if' disjunction)")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_121: assignment_expression | expression !':=' -static void * -_tmp_121_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // assignment_expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); - expr_ty assignment_expression_var; - if ( - (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression - ) - { - D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); - _res = assignment_expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); - } - { // expression !':=' + { // expression for_if_clauses if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c> _tmp_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; + asdl_comprehension_seq* for_if_clauses_var; if ( (expression_var = expression_rule(p)) // expression && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' + (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); - _res = expression_var; + D(fprintf(stderr, "%*c+ _tmp_106[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c%s _tmp_106[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); } _res = NULL; done: p->level--; - return _res; -} - -// _loop0_123: ',' (starred_expression | (assignment_expression | expression !':=') !'=') -static asdl_seq * -_loop0_123_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); - Token * _literal; - void *elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_259_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_123[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_122: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_123 -static asdl_seq * -_gather_122_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_123 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_123")); - void *elem; - asdl_seq * seq; - if ( - (elem = _tmp_259_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' - && - (seq = _loop0_123_rule(p)) // _loop0_123 - ) - { - D(fprintf(stderr, "%*c+ _gather_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_123")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_122[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_123")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_124: ',' kwargs -static void * -_tmp_124_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ',' kwargs - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); - Token * _literal; - asdl_seq* k; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (k = kwargs_rule(p)) // kwargs - ) - { - D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); - _res = k; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_124[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_126: ',' kwarg_or_starred -static asdl_seq * -_loop0_126_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' kwarg_or_starred - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); - Token * _literal; - KeywordOrStarred* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_125: kwarg_or_starred _loop0_126 -static asdl_seq * -_gather_125_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // kwarg_or_starred _loop0_126 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_126")); - KeywordOrStarred* elem; - asdl_seq * seq; - if ( - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred - && - (seq = _loop0_126_rule(p)) // _loop0_126 - ) - { - D(fprintf(stderr, "%*c+ _gather_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_126")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_125[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_126")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_128: ',' kwarg_or_double_starred -static asdl_seq * -_loop0_128_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' kwarg_or_double_starred - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); - Token * _literal; - KeywordOrStarred* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_127: kwarg_or_double_starred _loop0_128 -static asdl_seq * -_gather_127_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // kwarg_or_double_starred _loop0_128 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_128")); - KeywordOrStarred* elem; - asdl_seq * seq; - if ( - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred - && - (seq = _loop0_128_rule(p)) // _loop0_128 - ) - { - D(fprintf(stderr, "%*c+ _gather_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_128")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_127[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_128")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_130: ',' kwarg_or_starred -static asdl_seq * -_loop0_130_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' kwarg_or_starred - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); - Token * _literal; - KeywordOrStarred* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_130[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_129: kwarg_or_starred _loop0_130 -static asdl_seq * -_gather_129_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // kwarg_or_starred _loop0_130 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_130")); - KeywordOrStarred* elem; - asdl_seq * seq; - if ( - (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred - && - (seq = _loop0_130_rule(p)) // _loop0_130 - ) - { - D(fprintf(stderr, "%*c+ _gather_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_130")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_129[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_130")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_132: ',' kwarg_or_double_starred -static asdl_seq * -_loop0_132_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' kwarg_or_double_starred - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); - Token * _literal; - KeywordOrStarred* elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_131: kwarg_or_double_starred _loop0_132 -static asdl_seq * -_gather_131_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // kwarg_or_double_starred _loop0_132 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_132")); - KeywordOrStarred* elem; - asdl_seq * seq; - if ( - (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred - && - (seq = _loop0_132_rule(p)) // _loop0_132 - ) - { - D(fprintf(stderr, "%*c+ _gather_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_132")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_131[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_132")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_133: (',' star_target) -static asdl_seq * -_loop0_133_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (',' star_target) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_260_var; - while ( - (_tmp_260_var = _tmp_260_rule(p)) // ',' star_target - ) - { - _res = _tmp_260_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_135: ',' star_target -static asdl_seq * -_loop0_135_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' star_target - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = star_target_rule(p)) // star_target - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_134: star_target _loop0_135 -static asdl_seq * -_gather_134_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // star_target _loop0_135 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_135")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = star_target_rule(p)) // star_target - && - (seq = _loop0_135_rule(p)) // _loop0_135 - ) - { - D(fprintf(stderr, "%*c+ _gather_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_135")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_134[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_135")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_136: (',' star_target) -static asdl_seq * -_loop1_136_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (',' star_target) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_261_var; - while ( - (_tmp_261_var = _tmp_261_rule(p)) // ',' star_target - ) - { - _res = _tmp_261_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_136[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_137: !'*' star_target -static void * -_tmp_137_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // !'*' star_target - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); - expr_ty star_target_var; - if ( - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' - && - (star_target_var = star_target_rule(p)) // star_target - ) - { - D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); - _res = star_target_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_139: ',' del_target -static asdl_seq * -_loop0_139_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' del_target - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = del_target_rule(p)) // del_target - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_139[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_138: del_target _loop0_139 -static asdl_seq * -_gather_138_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // del_target _loop0_139 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_139")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = del_target_rule(p)) // del_target - && - (seq = _loop0_139_rule(p)) // _loop0_139 - ) - { - D(fprintf(stderr, "%*c+ _gather_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_139")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_138[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_139")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_141: ',' expression -static asdl_seq * -_loop0_141_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = expression_rule(p)) // expression - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_141[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_140: expression _loop0_141 -static asdl_seq * -_gather_140_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // expression _loop0_141 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_141")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = expression_rule(p)) // expression - && - (seq = _loop0_141_rule(p)) // _loop0_141 - ) - { - D(fprintf(stderr, "%*c+ _gather_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_141")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_140[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_141")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_143: ',' expression -static asdl_seq * -_loop0_143_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = expression_rule(p)) // expression - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_143[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_142: expression _loop0_143 -static asdl_seq * -_gather_142_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // expression _loop0_143 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_143")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = expression_rule(p)) // expression - && - (seq = _loop0_143_rule(p)) // _loop0_143 - ) - { - D(fprintf(stderr, "%*c+ _gather_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_143")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_142[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_143")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_145: ',' expression -static asdl_seq * -_loop0_145_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = expression_rule(p)) // expression - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_145[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_144: expression _loop0_145 -static asdl_seq * -_gather_144_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // expression _loop0_145 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_145")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = expression_rule(p)) // expression - && - (seq = _loop0_145_rule(p)) // _loop0_145 - ) - { - D(fprintf(stderr, "%*c+ _gather_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_145")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_144[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_145")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_147: ',' expression -static asdl_seq * -_loop0_147_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = expression_rule(p)) // expression - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_147[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_146: expression _loop0_147 -static asdl_seq * -_gather_146_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // expression _loop0_147 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression _loop0_147")); - expr_ty elem; - asdl_seq * seq; - if ( - (elem = expression_rule(p)) // expression - && - (seq = _loop0_147_rule(p)) // _loop0_147 - ) - { - D(fprintf(stderr, "%*c+ _gather_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression _loop0_147")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_146[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression _loop0_147")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_148: NEWLINE INDENT -static void * -_tmp_148_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // NEWLINE INDENT - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); - Token * indent_var; - Token * newline_var; - if ( - (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' - && - (indent_var = _PyPegen_expect_token(p, INDENT)) // token='INDENT' - ) - { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE INDENT")); - _res = _PyPegen_dummy_name(p, newline_var, indent_var); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE INDENT")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_149: -// | (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) -// | kwargs -static void * -_tmp_149_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // (','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - void *_tmp_262_var; - if ( - (_tmp_262_var = _tmp_262_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs - ) - { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - _res = _tmp_262_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs)")); - } - { // kwargs - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwargs")); - asdl_seq* kwargs_var; - if ( - (kwargs_var = kwargs_rule(p)) // kwargs - ) - { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwargs")); - _res = kwargs_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwargs")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_151: ',' (starred_expression !'=') -static asdl_seq * -_loop0_151_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' (starred_expression !'=') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression !'=')")); - Token * _literal; - void *elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_263_rule(p)) // starred_expression !'=' - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_151[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression !'=')")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_150: (starred_expression !'=') _loop0_151 -static asdl_seq * -_gather_150_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // (starred_expression !'=') _loop0_151 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_151")); - void *elem; - asdl_seq * seq; - if ( - (elem = _tmp_263_rule(p)) // starred_expression !'=' - && - (seq = _loop0_151_rule(p)) // _loop0_151 - ) - { - D(fprintf(stderr, "%*c+ _gather_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression !'=') _loop0_151")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_150[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression !'=') _loop0_151")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_152: args | expression for_if_clauses -static void * -_tmp_152_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // args - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); - expr_ty args_var; - if ( - (args_var = args_rule(p)) // args - ) - { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); - _res = args_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); - } - { // expression for_if_clauses - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); - expr_ty expression_var; - asdl_comprehension_seq* for_if_clauses_var; - if ( - (expression_var = expression_rule(p)) // expression - && - (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses - ) - { - D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); - _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_153: args ',' -static void * -_tmp_153_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // args ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); - Token * _literal; - expr_ty args_var; - if ( - (args_var = args_rule(p)) // args - && - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); - _res = _PyPegen_dummy_name(p, args_var, _literal); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ','")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_154: ',' | ')' -static void * -_tmp_154_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - { // ')' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 8)) // token=')' - ) - { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_155: 'True' | 'False' | 'None' -static void * -_tmp_155_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // 'True' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' - ) - { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); - } - { // 'False' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' - ) - { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); - } - { // 'None' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' - ) - { - D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_156: NAME '=' -static void * -_tmp_156_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // NAME '=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); - Token * _literal; - expr_ty name_var; - if ( - (name_var = _PyPegen_name_token(p)) // NAME - && - (_literal = _PyPegen_expect_token(p, 22)) // token='=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); - _res = _PyPegen_dummy_name(p, name_var, _literal); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_157: NAME STRING | SOFT_KEYWORD -static void * -_tmp_157_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // NAME STRING - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); - expr_ty name_var; - expr_ty string_var; - if ( - (name_var = _PyPegen_name_token(p)) // NAME - && - (string_var = _PyPegen_string_token(p)) // STRING - ) - { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); - _res = _PyPegen_dummy_name(p, name_var, string_var); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); - } - { // SOFT_KEYWORD - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); - expr_ty soft_keyword_var; - if ( - (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD - ) - { - D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); - _res = soft_keyword_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_158: 'else' | ':' -static void * -_tmp_158_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // 'else' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 671)) // token='else' - ) - { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); - } - { // ':' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' - ) - { - D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_159: '=' | ':=' -static void * -_tmp_159_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); - } - { // ':=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 53)) // token=':=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_160: list | tuple | genexp | 'True' | 'None' | 'False' -static void * -_tmp_160_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // list - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); - expr_ty list_var; - if ( - (list_var = list_rule(p)) // list - ) - { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); - _res = list_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); - } - { // tuple - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); - expr_ty tuple_var; - if ( - (tuple_var = tuple_rule(p)) // tuple - ) - { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); - _res = tuple_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); - } - { // genexp - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); - expr_ty genexp_var; - if ( - (genexp_var = genexp_rule(p)) // genexp - ) - { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); - _res = genexp_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); - } - { // 'True' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 610)) // token='True' - ) - { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); - } - { // 'None' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 611)) // token='None' - ) - { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); - } - { // 'False' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); - Token * _keyword; - if ( - (_keyword = _PyPegen_expect_token(p, 612)) // token='False' - ) - { - D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); - _res = _keyword; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_161: '=' | ':=' -static void * -_tmp_161_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); - } - { // ':=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 53)) // token=':=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_162: star_named_expressions -static asdl_seq * -_loop0_162_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // star_named_expressions - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); - asdl_expr_seq* star_named_expressions_var; - while ( - (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions - ) - { - _res = star_named_expressions_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_162[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_163: (star_targets '=') -static asdl_seq * -_loop0_163_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (star_targets '=') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_264_var; - while ( - (_tmp_264_var = _tmp_264_rule(p)) // star_targets '=' - ) - { - _res = _tmp_264_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_163[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_164: (star_targets '=') -static asdl_seq * -_loop0_164_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (star_targets '=') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_265_var; - while ( - (_tmp_265_var = _tmp_265_rule(p)) // star_targets '=' - ) - { - _res = _tmp_265_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_164[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_165: '[' | '(' | '{' -static void * -_tmp_165_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '[' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 9)) // token='[' - ) - { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); - } - { // '(' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' - ) - { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); - } - { // '{' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 25)) // token='{' - ) - { - D(fprintf(stderr, "%*c+ _tmp_165[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_165[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_166: '[' | '{' -static void * -_tmp_166_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '[' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 9)) // token='[' - ) - { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); - } - { // '{' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 25)) // token='{' - ) - { - D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_167: '[' | '{' -static void * -_tmp_167_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '[' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 9)) // token='[' - ) - { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); - } - { // '{' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 25)) // token='{' - ) - { - D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_168: slash_no_default | slash_with_default -static void * -_tmp_168_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // slash_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); - asdl_arg_seq* slash_no_default_var; - if ( - (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); - _res = slash_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); - } - { // slash_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); - SlashWithDefault* slash_with_default_var; - if ( - (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); - _res = slash_with_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_169: param_maybe_default -static asdl_seq * -_loop0_169_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; - while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default - ) - { - _res = param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_169[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_170: param_no_default -static asdl_seq * -_loop0_170_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_170[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default - ) - { - _res = param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_170[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_171: param_no_default -static asdl_seq * -_loop0_171_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_171[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default - ) - { - _res = param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_171[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_172: param_no_default -static asdl_seq * -_loop1_172_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_172[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - while ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default - ) - { - _res = param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_172[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_173: slash_no_default | slash_with_default -static void * -_tmp_173_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // slash_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); - asdl_arg_seq* slash_no_default_var; - if ( - (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); - _res = slash_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); - } - { // slash_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_173[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); - SlashWithDefault* slash_with_default_var; - if ( - (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_173[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); - _res = slash_with_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_173[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_174: param_maybe_default -static asdl_seq * -_loop0_174_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_174[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; - while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default - ) - { - _res = param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_174[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_175: ',' | param_no_default -static void * -_tmp_175_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - { // param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_175[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - if ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_175[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); - _res = param_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_175[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_176: param_maybe_default -static asdl_seq * -_loop0_176_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_176[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; - while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default - ) - { - _res = param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_176[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_177: param_maybe_default -static asdl_seq * -_loop1_177_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_177[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; - while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default - ) - { - _res = param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_177[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_178: ')' | ',' -static void * -_tmp_178_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ')' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 8)) // token=')' - ) - { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); - } - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_178[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_178[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_178[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_179: ')' | ',' (')' | '**') -static void * -_tmp_179_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ')' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 8)) // token=')' - ) - { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); - } - { // ',' (')' | '**') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_179[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - Token * _literal; - void *_tmp_266_var; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (_tmp_266_var = _tmp_266_rule(p)) // ')' | '**' - ) - { - D(fprintf(stderr, "%*c+ _tmp_179[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_266_var); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_179[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_180: param_no_default | ',' -static void * -_tmp_180_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - if ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); - _res = param_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_180[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_180[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_180[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_181: param_maybe_default -static asdl_seq * -_loop0_181_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_181[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_maybe_default")); - NameDefaultPair* param_maybe_default_var; - while ( - (param_maybe_default_var = param_maybe_default_rule(p)) // param_maybe_default - ) - { - _res = param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_181[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_182: param_no_default | ',' -static void * -_tmp_182_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); - arg_ty param_no_default_var; - if ( - (param_no_default_var = param_no_default_rule(p)) // param_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); - _res = param_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); - } - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_182[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_182[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_182[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_183: '*' | '**' | '/' -static void * -_tmp_183_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // '*' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 16)) // token='*' - ) - { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); - } - { // '**' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 35)) // token='**' - ) - { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); - } - { // '/' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_183[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 17)) // token='/' - ) - { - D(fprintf(stderr, "%*c+ _tmp_183[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_183[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop1_184: param_with_default -static asdl_seq * -_loop1_184_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // param_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_184[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); - NameDefaultPair* param_with_default_var; - while ( - (param_with_default_var = param_with_default_rule(p)) // param_with_default - ) - { - _res = param_with_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_184[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_185: lambda_slash_no_default | lambda_slash_with_default -static void * -_tmp_185_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // lambda_slash_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); - asdl_arg_seq* lambda_slash_no_default_var; - if ( - (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); - _res = lambda_slash_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); - } - { // lambda_slash_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_185[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); - SlashWithDefault* lambda_slash_with_default_var; - if ( - (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_185[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); - _res = lambda_slash_with_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_185[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_186: lambda_param_maybe_default -static asdl_seq * -_loop0_186_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_186[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; - while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default - ) - { - _res = lambda_param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_186[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_187: lambda_param_no_default -static asdl_seq * -_loop0_187_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_187[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default - ) - { - _res = lambda_param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_187[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_188: lambda_param_no_default -static asdl_seq * -_loop0_188_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_188[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - while ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default - ) - { - _res = lambda_param_no_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_188[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop0_190: ',' lambda_param -static asdl_seq * -_loop0_190_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' lambda_param - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_190[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); - Token * _literal; - arg_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = lambda_param_rule(p)) // lambda_param - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_190[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' lambda_param")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_189: lambda_param _loop0_190 -static asdl_seq * -_gather_189_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // lambda_param _loop0_190 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_189[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_190")); - arg_ty elem; - asdl_seq * seq; - if ( - (elem = lambda_param_rule(p)) // lambda_param - && - (seq = _loop0_190_rule(p)) // _loop0_190 - ) - { - D(fprintf(stderr, "%*c+ _gather_189[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_190")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_189[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_190")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_191: lambda_slash_no_default | lambda_slash_with_default -static void * -_tmp_191_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // lambda_slash_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); - asdl_arg_seq* lambda_slash_no_default_var; - if ( - (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); - _res = lambda_slash_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); - } - { // lambda_slash_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_191[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); - SlashWithDefault* lambda_slash_with_default_var; - if ( - (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_191[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); - _res = lambda_slash_with_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_191[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_192: lambda_param_maybe_default -static asdl_seq * -_loop0_192_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_192[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; - while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default - ) - { - _res = lambda_param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_192[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_193: ',' | lambda_param_no_default -static void * -_tmp_193_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - { // lambda_param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_193[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - if ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_193[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - _res = lambda_param_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_193[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_194: lambda_param_maybe_default -static asdl_seq * -_loop0_194_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_194[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; - while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default - ) - { - _res = lambda_param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_194[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_195: lambda_param_maybe_default -static asdl_seq * -_loop1_195_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_195[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; - while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default - ) - { - _res = lambda_param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_195[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_196: lambda_param_with_default -static asdl_seq * -_loop1_196_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_with_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop1_196[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); - NameDefaultPair* lambda_param_with_default_var; - while ( - (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default - ) - { - _res = lambda_param_with_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_196[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _tmp_197: ':' | ',' (':' | '**') -static void * -_tmp_197_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ':' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' - ) - { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); - } - { // ',' (':' | '**') - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_197[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - Token * _literal; - void *_tmp_267_var; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (_tmp_267_var = _tmp_267_rule(p)) // ':' | '**' - ) - { - D(fprintf(stderr, "%*c+ _tmp_197[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_267_var); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_197[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_198: lambda_param_no_default | ',' -static void * -_tmp_198_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // lambda_param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - if ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - _res = lambda_param_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - { // ',' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_198[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - ) - { - D(fprintf(stderr, "%*c+ _tmp_198[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_198[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_199: lambda_param_maybe_default -static asdl_seq * -_loop0_199_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // lambda_param_maybe_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_199[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_maybe_default")); - NameDefaultPair* lambda_param_maybe_default_var; - while ( - (lambda_param_maybe_default_var = lambda_param_maybe_default_rule(p)) // lambda_param_maybe_default - ) - { - _res = lambda_param_maybe_default_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_199[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_maybe_default")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; + return _res; } -// _tmp_200: lambda_param_no_default | ',' +// _tmp_107: args ',' static void * -_tmp_200_rule(Parser *p) +_tmp_107_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38145,43 +32057,27 @@ _tmp_200_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // lambda_param_no_default - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - arg_ty lambda_param_no_default_var; - if ( - (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default - ) - { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); - _res = lambda_param_no_default_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); - } - { // ',' + { // args ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_200[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args ','")); Token * _literal; + expr_ty args_var; if ( + (args_var = args_rule(p)) // args + && (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_200[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_107[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args ','")); + _res = _PyPegen_dummy_name(p, args_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_200[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _tmp_107[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args ','")); } _res = NULL; done: @@ -38189,9 +32085,9 @@ _tmp_200_rule(Parser *p) return _res; } -// _tmp_201: '*' | '**' | '/' +// _tmp_108: ',' | ')' static void * -_tmp_201_rule(Parser *p) +_tmp_108_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38202,62 +32098,43 @@ _tmp_201_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '*' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 16)) // token='*' - ) - { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); - } - { // '**' + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 35)) // token='**' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c%s _tmp_108[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } - { // '/' + { // ')' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_201[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c> _tmp_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 17)) // token='/' + (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_201[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c+ _tmp_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_201[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); + D(fprintf(stderr, "%*c%s _tmp_108[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } _res = NULL; done: @@ -38265,9 +32142,9 @@ _tmp_201_rule(Parser *p) return _res; } -// _tmp_202: ',' | ')' | ':' +// _tmp_109: 'True' | 'False' | 'None' static void * -_tmp_202_rule(Parser *p) +_tmp_109_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38278,62 +32155,62 @@ _tmp_202_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ',' + { // 'True' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + Token * _keyword; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (_keyword = _PyPegen_expect_token(p, 610)) // token='True' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_109[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _tmp_109[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } - { // ')' + { // 'False' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); + Token * _keyword; if ( - (_literal = _PyPegen_expect_token(p, 8)) // token=')' + (_keyword = _PyPegen_expect_token(p, 612)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_109[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); + _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c%s _tmp_109[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } - { // ':' + { // 'None' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_202[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); + Token * _keyword; if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' + (_keyword = _PyPegen_expect_token(p, 611)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_202[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_109[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); + _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_202[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c%s _tmp_109[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } _res = NULL; done: @@ -38341,9 +32218,9 @@ _tmp_202_rule(Parser *p) return _res; } -// _tmp_203: bitwise_or ((',' bitwise_or))* ','? +// _tmp_110: NAME '=' static void * -_tmp_203_rule(Parser *p) +_tmp_110_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38354,31 +32231,27 @@ _tmp_203_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // bitwise_or ((',' bitwise_or))* ','? + { // NAME '=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_203[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); - asdl_seq * _loop0_268_var; - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - expr_ty bitwise_or_var; + D(fprintf(stderr, "%*c> _tmp_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME '='")); + Token * _literal; + expr_ty name_var; if ( - (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or - && - (_loop0_268_var = _loop0_268_rule(p)) // ((',' bitwise_or))* + (name_var = _PyPegen_name_token(p)) // NAME && - (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? + (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_203[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); - _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_268_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_110[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME '='")); + _res = _PyPegen_dummy_name(p, name_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_203[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + D(fprintf(stderr, "%*c%s _tmp_110[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME '='")); } _res = NULL; done: @@ -38386,9 +32259,9 @@ _tmp_203_rule(Parser *p) return _res; } -// _loop0_205: ',' dotted_name -static asdl_seq * -_loop0_205_rule(Parser *p) +// _tmp_111: NAME STRING | SOFT_KEYWORD +static void * +_tmp_111_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38397,105 +32270,48 @@ _loop0_205_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' dotted_name + { // NAME STRING if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_205[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); - Token * _literal; - expr_ty elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + expr_ty name_var; + expr_ty string_var; + if ( + (name_var = _PyPegen_name_token(p)) // NAME && - (elem = dotted_name_rule(p)) // dotted_name + (string_var = _PyPegen_string_token(p)) // STRING ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NAME STRING")); + _res = _PyPegen_dummy_name(p, name_var, string_var); + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_205[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_name")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_204: dotted_name _loop0_205 -static asdl_seq * -_gather_204_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_111[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME STRING")); } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // dotted_name _loop0_205 + { // SOFT_KEYWORD if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_204[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_205")); - expr_ty elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + expr_ty soft_keyword_var; if ( - (elem = dotted_name_rule(p)) // dotted_name - && - (seq = _loop0_205_rule(p)) // _loop0_205 + (soft_keyword_var = _PyPegen_soft_keyword_token(p)) // SOFT_KEYWORD ) { - D(fprintf(stderr, "%*c+ _gather_204[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_205")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "SOFT_KEYWORD")); + _res = soft_keyword_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_204[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_205")); + D(fprintf(stderr, "%*c%s _tmp_111[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "SOFT_KEYWORD")); } _res = NULL; done: @@ -38503,9 +32319,9 @@ _gather_204_rule(Parser *p) return _res; } -// _loop0_207: ',' (expression ['as' star_target]) -static asdl_seq * -_loop0_207_rule(Parser *p) +// _tmp_112: 'else' | ':' +static void * +_tmp_112_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38514,105 +32330,45 @@ _loop0_207_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' (expression ['as' star_target]) + { // 'else' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_207[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); - Token * _literal; - void *elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_269_rule(p)) // expression ['as' star_target] + D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'else'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 671)) // token='else' ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'else'")); + _res = _keyword; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_207[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_206: (expression ['as' star_target]) _loop0_207 -static asdl_seq * -_gather_206_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'else'")); } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_207 + { // ':' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_206[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); - void *elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + Token * _literal; if ( - (elem = _tmp_269_rule(p)) // expression ['as' star_target] - && - (seq = _loop0_207_rule(p)) // _loop0_207 + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _gather_206[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_206[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_207")); + D(fprintf(stderr, "%*c%s _tmp_112[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; done: @@ -38620,9 +32376,9 @@ _gather_206_rule(Parser *p) return _res; } -// _loop0_209: ',' (expressions ['as' star_target]) -static asdl_seq * -_loop0_209_rule(Parser *p) +// _tmp_113: '=' | ':=' +static void * +_tmp_113_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38631,105 +32387,45 @@ _loop0_209_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' (expressions ['as' star_target]) + { // '=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_209[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; - void *elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_270_rule(p)) // expressions ['as' star_target] + if ( + (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); + _res = _literal; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_209[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_208: (expressions ['as' star_target]) _loop0_209 -static asdl_seq * -_gather_208_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_209 + { // ':=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_208[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); - void *elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':='")); + Token * _literal; if ( - (elem = _tmp_270_rule(p)) // expressions ['as' star_target] - && - (seq = _loop0_209_rule(p)) // _loop0_209 + (_literal = _PyPegen_expect_token(p, 53)) // token=':=' ) { - D(fprintf(stderr, "%*c+ _gather_208[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':='")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_208[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_209")); + D(fprintf(stderr, "%*c%s _tmp_113[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':='")); } _res = NULL; done: @@ -38737,85 +32433,9 @@ _gather_208_rule(Parser *p) return _res; } -// _loop0_211: ',' (expression ['as' star_target]) -static asdl_seq * -_loop0_211_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' (expression ['as' star_target]) - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _loop0_211[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); - Token * _literal; - void *elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_271_rule(p)) // expression ['as' star_target] - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_211[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_210: (expression ['as' star_target]) _loop0_211 -static asdl_seq * -_gather_210_rule(Parser *p) +// _tmp_114: list | tuple | genexp | 'True' | 'None' | 'False' +static void * +_tmp_114_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -38824,203 +32444,121 @@ _gather_210_rule(Parser *p) p->level--; return NULL; } - asdl_seq * _res = NULL; + void * _res = NULL; int _mark = p->mark; - { // (expression ['as' star_target]) _loop0_211 + { // list if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_210[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); - void *elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "list")); + expr_ty list_var; if ( - (elem = _tmp_271_rule(p)) // expression ['as' star_target] - && - (seq = _loop0_211_rule(p)) // _loop0_211 + (list_var = list_rule(p)) // list ) { - D(fprintf(stderr, "%*c+ _gather_210[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "list")); + _res = list_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_210[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_211")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_213: ',' (expressions ['as' star_target]) -static asdl_seq * -_loop0_213_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "list")); } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // ',' (expressions ['as' star_target]) + { // tuple if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_213[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); - Token * _literal; - void *elem; - while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_272_rule(p)) // expressions ['as' star_target] - ) - { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_213[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _gather_212: (expressions ['as' star_target]) _loop0_213 -static asdl_seq * -_gather_212_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "tuple")); + expr_ty tuple_var; + if ( + (tuple_var = tuple_rule(p)) // tuple + ) + { + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "tuple")); + _res = tuple_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "tuple")); } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // (expressions ['as' star_target]) _loop0_213 + { // genexp if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_212[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); - void *elem; - asdl_seq * seq; + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "genexp")); + expr_ty genexp_var; if ( - (elem = _tmp_272_rule(p)) // expressions ['as' star_target] - && - (seq = _loop0_213_rule(p)) // _loop0_213 + (genexp_var = genexp_rule(p)) // genexp ) { - D(fprintf(stderr, "%*c+ _gather_212[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "genexp")); + _res = genexp_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_212[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_213")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_214: 'except' | 'finally' -static void * -_tmp_214_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "genexp")); } - if (p->error_indicator) { - p->level--; - return NULL; + { // 'True' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'True'")); + Token * _keyword; + if ( + (_keyword = _PyPegen_expect_token(p, 610)) // token='True' + ) + { + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'True'")); + _res = _keyword; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'True'")); } - void * _res = NULL; - int _mark = p->mark; - { // 'except' + { // 'None' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'None'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 663)) // token='except' + (_keyword = _PyPegen_expect_token(p, 611)) // token='None' ) { - D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'None'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'None'")); } - { // 'finally' + { // 'False' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_214[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c> _tmp_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'False'")); Token * _keyword; if ( - (_keyword = _PyPegen_expect_token(p, 659)) // token='finally' + (_keyword = _PyPegen_expect_token(p, 612)) // token='False' ) { - D(fprintf(stderr, "%*c+ _tmp_214[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c+ _tmp_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'False'")); _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_214[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); + D(fprintf(stderr, "%*c%s _tmp_114[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'False'")); } _res = NULL; done: @@ -39028,9 +32566,9 @@ _tmp_214_rule(Parser *p) return _res; } -// _loop0_215: block +// _loop0_115: star_named_expressions static asdl_seq * -_loop0_215_rule(Parser *p) +_loop0_115_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39050,18 +32588,18 @@ _loop0_215_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // block + { // star_named_expressions if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_215[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); - asdl_stmt_seq* block_var; + D(fprintf(stderr, "%*c> _loop0_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + asdl_expr_seq* star_named_expressions_var; while ( - (block_var = block_rule(p)) // block + (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions ) { - _res = block_var; + _res = star_named_expressions_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -39078,8 +32616,8 @@ _loop0_215_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_215[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); + D(fprintf(stderr, "%*c%s _loop0_115[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -39095,9 +32633,9 @@ _loop0_215_rule(Parser *p) return _seq; } -// _loop1_216: except_block +// _loop0_116: (star_targets '=') static asdl_seq * -_loop1_216_rule(Parser *p) +_loop0_116_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39117,18 +32655,18 @@ _loop1_216_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // except_block + { // (star_targets '=') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_216[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_block")); - excepthandler_ty except_block_var; + D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_150_var; while ( - (except_block_var = except_block_rule(p)) // except_block + (_tmp_150_var = _tmp_150_rule(p)) // star_targets '=' ) { - _res = except_block_var; + _res = _tmp_150_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -39145,13 +32683,8 @@ _loop1_216_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_216[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_block")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _loop0_116[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -39167,9 +32700,9 @@ _loop1_216_rule(Parser *p) return _seq; } -// _tmp_217: 'as' NAME +// _tmp_117: '[' | '(' | '{' static void * -_tmp_217_rule(Parser *p) +_tmp_117_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39180,176 +32713,72 @@ _tmp_217_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // '[' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_217[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_217[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_217[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _loop0_218: block -static asdl_seq * -_loop0_218_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // block + { // '(' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_218[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); - asdl_stmt_seq* block_var; - while ( - (block_var = block_rule(p)) // block + D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - _res = block_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + _res = _literal; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_218[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); - p->level--; - return _seq; -} - -// _loop1_219: except_star_block -static asdl_seq * -_loop1_219_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void *_res = NULL; - int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // except_star_block + { // '{' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop1_219[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "except_star_block")); - excepthandler_ty except_star_block_var; - while ( - (except_star_block_var = except_star_block_rule(p)) // except_star_block + D(fprintf(stderr, "%*c> _tmp_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - _res = except_star_block_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; - } - _children[_n++] = _res; - _mark = p->mark; + D(fprintf(stderr, "%*c+ _tmp_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + _res = _literal; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_219[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "except_star_block")); - } - if (_n == 0 || p->error_indicator) { - PyMem_Free(_children); - p->level--; - return NULL; - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _tmp_220: expression ['as' NAME] +// _tmp_118: '[' | '{' static void * -_tmp_220_rule(Parser *p) +_tmp_118_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39360,69 +32789,43 @@ _tmp_220_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // expression ['as' NAME] + { // '[' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_220[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - expr_ty expression_var; + D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + Token * _literal; if ( - (expression_var = expression_rule(p)) // expression - && - (_opt_var = _tmp_273_rule(p), !p->error_indicator) // ['as' NAME] + (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_220[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); - _res = _PyPegen_dummy_name(p, expression_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_220[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_221: 'as' NAME -static void * -_tmp_221_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } - void * _res = NULL; - int _mark = p->mark; - { // 'as' NAME + { // '{' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_221[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_221[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_118[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_221[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_118[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; done: @@ -39430,9 +32833,9 @@ _tmp_221_rule(Parser *p) return _res; } -// _tmp_222: 'as' NAME +// _tmp_119: slash_no_default | slash_with_default static void * -_tmp_222_rule(Parser *p) +_tmp_119_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39443,68 +32846,43 @@ _tmp_222_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // slash_no_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_222[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + asdl_arg_seq* slash_no_default_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (slash_no_default_var = slash_no_default_rule(p)) // slash_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_222[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_no_default")); + _res = slash_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_222[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_223: 'as' NAME -static void * -_tmp_223_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_119[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_no_default")); } - void * _res = NULL; - int _mark = p->mark; - { // 'as' NAME + { // slash_with_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_223[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + SlashWithDefault* slash_with_default_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_223[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_223[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_119[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } _res = NULL; done: @@ -39512,9 +32890,9 @@ _tmp_223_rule(Parser *p) return _res; } -// _tmp_224: 'as' NAME +// _tmp_120: ',' | param_no_default static void * -_tmp_224_rule(Parser *p) +_tmp_120_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39525,27 +32903,43 @@ _tmp_224_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_224[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_224[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_224[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + } + { // param_no_default + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + arg_ty param_no_default_var; + if ( + (param_no_default_var = param_no_default_rule(p)) // param_no_default + ) + { + D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + _res = param_no_default_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } _res = NULL; done: @@ -39553,9 +32947,9 @@ _tmp_224_rule(Parser *p) return _res; } -// _tmp_225: NEWLINE | ':' +// _tmp_121: ')' | ',' static void * -_tmp_225_rule(Parser *p) +_tmp_121_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39566,43 +32960,43 @@ _tmp_225_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // NEWLINE + { // ')' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); - Token * newline_var; + D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + Token * _literal; if ( - (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); - _res = newline_var; + D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); + D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } - { // ':' + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_225[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_225[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_225[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; done: @@ -39610,9 +33004,9 @@ _tmp_225_rule(Parser *p) return _res; } -// _tmp_226: 'as' NAME +// _tmp_122: ')' | ',' (')' | '**') static void * -_tmp_226_rule(Parser *p) +_tmp_122_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39623,68 +33017,46 @@ _tmp_226_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // ')' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_226[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_226[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_226[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_227: 'as' NAME -static void * -_tmp_227_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } - void * _res = NULL; - int _mark = p->mark; - { // 'as' NAME + { // ',' (')' | '**') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_227[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + Token * _literal; + void *_tmp_163_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (name_var = _PyPegen_name_token(p)) // NAME + (_tmp_163_var = _tmp_163_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_227[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_163_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_227[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; done: @@ -39692,9 +33064,9 @@ _tmp_227_rule(Parser *p) return _res; } -// _tmp_228: positional_patterns ',' +// _tmp_123: param_no_default | ',' static void * -_tmp_228_rule(Parser *p) +_tmp_123_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39705,27 +33077,43 @@ _tmp_228_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // positional_patterns ',' + { // param_no_default + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + arg_ty param_no_default_var; + if ( + (param_no_default_var = param_no_default_rule(p)) // param_no_default + ) + { + D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_no_default")); + _res = param_no_default_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); + } + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_228[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c> _tmp_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; - asdl_pattern_seq* positional_patterns_var; if ( - (positional_patterns_var = positional_patterns_rule(p)) // positional_patterns - && (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_228[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); - _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); + D(fprintf(stderr, "%*c+ _tmp_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_228[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); + D(fprintf(stderr, "%*c%s _tmp_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; done: @@ -39733,9 +33121,9 @@ _tmp_228_rule(Parser *p) return _res; } -// _tmp_229: '->' expression +// _tmp_124: '*' | '**' | '/' static void * -_tmp_229_rule(Parser *p) +_tmp_124_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39746,113 +33134,62 @@ _tmp_229_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '->' expression + { // '*' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_229[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); Token * _literal; - expr_ty expression_var; if ( - (_literal = _PyPegen_expect_token(p, 51)) // token='->' - && - (expression_var = expression_rule(p)) // expression + (_literal = _PyPegen_expect_token(p, 16)) // token='*' ) { - D(fprintf(stderr, "%*c+ _tmp_229[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); - _res = _PyPegen_dummy_name(p, _literal, expression_var); + D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_229[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_230: '->' expression -static void * -_tmp_230_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_124[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } - void * _res = NULL; - int _mark = p->mark; - { // '->' expression + { // '**' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_230[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'->' expression")); + D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; - expr_ty expression_var; if ( - (_literal = _PyPegen_expect_token(p, 51)) // token='->' - && - (expression_var = expression_rule(p)) // expression + (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_230[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'->' expression")); - _res = _PyPegen_dummy_name(p, _literal, expression_var); + D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_230[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'->' expression")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_231: '(' arguments? ')' -static void * -_tmp_231_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_124[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } - void * _res = NULL; - int _mark = p->mark; - { // '(' arguments? ')' + { // '/' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_231[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c> _tmp_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); Token * _literal; - Token * _literal_1; - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' - && - (_opt_var = arguments_rule(p), !p->error_indicator) // arguments? - && - (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' + (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_231[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); - _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); + D(fprintf(stderr, "%*c+ _tmp_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_231[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c%s _tmp_124[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } _res = NULL; done: @@ -39860,9 +33197,9 @@ _tmp_231_rule(Parser *p) return _res; } -// _tmp_232: '(' arguments? ')' +// _tmp_125: lambda_slash_no_default | lambda_slash_with_default static void * -_tmp_232_rule(Parser *p) +_tmp_125_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39873,31 +33210,43 @@ _tmp_232_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '(' arguments? ')' + { // lambda_slash_no_default + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + asdl_arg_seq* lambda_slash_no_default_var; + if ( + (lambda_slash_no_default_var = lambda_slash_no_default_rule(p)) // lambda_slash_no_default + ) + { + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_no_default")); + _res = lambda_slash_no_default_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_no_default")); + } + { // lambda_slash_with_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_232[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); - Token * _literal; - Token * _literal_1; - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings + D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + SlashWithDefault* lambda_slash_with_default_var; if ( - (_literal = _PyPegen_expect_token(p, 7)) // token='(' - && - (_opt_var = arguments_rule(p), !p->error_indicator) // arguments? - && - (_literal_1 = _PyPegen_expect_token(p, 8)) // token=')' + (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_232[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' arguments? ')'")); - _res = _PyPegen_dummy_name(p, _literal, _opt_var, _literal_1); + D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + _res = lambda_slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_232[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' arguments? ')'")); + D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } _res = NULL; done: @@ -39905,9 +33254,9 @@ _tmp_232_rule(Parser *p) return _res; } -// _loop0_234: ',' double_starred_kvpair +// _loop0_126: ',' lambda_param static asdl_seq * -_loop0_234_rule(Parser *p) +_loop0_126_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39927,18 +33276,18 @@ _loop0_234_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' double_starred_kvpair + { // ',' lambda_param if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_234[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' lambda_param")); Token * _literal; - KeyValuePair* elem; + arg_ty elem; while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair + (elem = lambda_param_rule(p)) // lambda_param ) { _res = elem; @@ -39964,8 +33313,8 @@ _loop0_234_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_234[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' double_starred_kvpair")); + D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' lambda_param")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -39981,9 +33330,9 @@ _loop0_234_rule(Parser *p) return _seq; } -// _gather_233: double_starred_kvpair _loop0_234 +// _gather_127: lambda_param _loop0_126 static asdl_seq * -_gather_233_rule(Parser *p) +_gather_127_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -39994,27 +33343,27 @@ _gather_233_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // double_starred_kvpair _loop0_234 + { // lambda_param _loop0_126 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _gather_233[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_234")); - KeyValuePair* elem; + D(fprintf(stderr, "%*c> _gather_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_126")); + arg_ty elem; asdl_seq * seq; if ( - (elem = double_starred_kvpair_rule(p)) // double_starred_kvpair + (elem = lambda_param_rule(p)) // lambda_param && - (seq = _loop0_234_rule(p)) // _loop0_234 + (seq = _loop0_126_rule(p)) // _loop0_126 ) { - D(fprintf(stderr, "%*c+ _gather_233[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "double_starred_kvpair _loop0_234")); + D(fprintf(stderr, "%*c+ _gather_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param _loop0_126")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_233[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "double_starred_kvpair _loop0_234")); + D(fprintf(stderr, "%*c%s _gather_127[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param _loop0_126")); } _res = NULL; done: @@ -40022,9 +33371,9 @@ _gather_233_rule(Parser *p) return _res; } -// _tmp_235: '}' | ',' +// _tmp_128: ',' | lambda_param_no_default static void * -_tmp_235_rule(Parser *p) +_tmp_128_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40035,43 +33384,43 @@ _tmp_235_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '}' + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 26)) // token='}' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c%s _tmp_128[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } - { // ',' + { // lambda_param_no_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_235[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + arg_ty lambda_param_no_default_var; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_235[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_128[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_235[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _tmp_128[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } _res = NULL; done: @@ -40079,9 +33428,9 @@ _tmp_235_rule(Parser *p) return _res; } -// _tmp_236: '}' | ',' +// _tmp_129: ':' | ',' (':' | '**') static void * -_tmp_236_rule(Parser *p) +_tmp_129_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40092,43 +33441,46 @@ _tmp_236_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '}' + { // ':' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 26)) // token='}' + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - { // ',' + { // ',' (':' | '**') if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_236[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); + D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; + void *_tmp_164_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (_tmp_164_var = _tmp_164_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_236[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_164_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_236[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); + D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; done: @@ -40136,9 +33488,9 @@ _tmp_236_rule(Parser *p) return _res; } -// _tmp_237: '=' | '!' | ':' | '}' +// _tmp_130: lambda_param_no_default | ',' static void * -_tmp_237_rule(Parser *p) +_tmp_130_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40149,81 +33501,43 @@ _tmp_237_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 22)) // token='=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); - } - { // '!' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 54)) // token='!' - ) - { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); - } - { // ':' + { // lambda_param_no_default if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + arg_ty lambda_param_no_default_var; if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' + (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + _res = lambda_param_no_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } - { // '}' + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_237[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 26)) // token='}' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_237[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_237[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; done: @@ -40231,9 +33545,9 @@ _tmp_237_rule(Parser *p) return _res; } -// _tmp_238: '!' | ':' | '}' +// _tmp_131: bitwise_or ((',' bitwise_or))* ','? static void * -_tmp_238_rule(Parser *p) +_tmp_131_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40244,72 +33558,117 @@ _tmp_238_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '!' + { // bitwise_or ((',' bitwise_or))* ','? if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + asdl_seq * _loop0_165_var; + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + expr_ty bitwise_or_var; if ( - (_literal = _PyPegen_expect_token(p, 54)) // token='!' + (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or + && + (_loop0_165_var = _loop0_165_rule(p)) // ((',' bitwise_or))* + && + (_opt_var = _PyPegen_expect_token(p, 12), !p->error_indicator) // ','? ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); + _res = _PyPegen_dummy_name(p, bitwise_or_var, _loop0_165_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); + D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "bitwise_or ((',' bitwise_or))* ','?")); } - { // ':' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' - ) - { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + _res = NULL; + done: + p->level--; + return _res; +} + +// _loop0_132: ',' dotted_name +static asdl_seq * +_loop0_132_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } - { // '}' + if (p->error_indicator) { + p->level--; + return NULL; + } + void *_res = NULL; + int _mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' dotted_name if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_238[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' dotted_name")); Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 26)) // token='}' + expr_ty elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = dotted_name_rule(p)) // dotted_name ) { - D(fprintf(stderr, "%*c+ _tmp_238[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); - _res = _literal; - goto done; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_238[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' dotted_name")); } - _res = NULL; - done: + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); p->level--; - return _res; + return _seq; } -// _tmp_239: '!' NAME -static void * -_tmp_239_rule(Parser *p) +// _gather_133: dotted_name _loop0_132 +static asdl_seq * +_gather_133_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40318,29 +33677,29 @@ _tmp_239_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - { // '!' NAME + { // dotted_name _loop0_132 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_239[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); - Token * _literal; - expr_ty name_var; + D(fprintf(stderr, "%*c> _gather_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_132")); + expr_ty elem; + asdl_seq * seq; if ( - (_literal = _PyPegen_expect_token(p, 54)) // token='!' + (elem = dotted_name_rule(p)) // dotted_name && - (name_var = _PyPegen_name_token(p)) // NAME + (seq = _loop0_132_rule(p)) // _loop0_132 ) { - D(fprintf(stderr, "%*c+ _tmp_239[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); - _res = _PyPegen_dummy_name(p, _literal, name_var); + D(fprintf(stderr, "%*c+ _gather_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "dotted_name _loop0_132")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_239[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c%s _gather_133[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "dotted_name _loop0_132")); } _res = NULL; done: @@ -40348,9 +33707,9 @@ _tmp_239_rule(Parser *p) return _res; } -// _tmp_240: ':' | '}' -static void * -_tmp_240_rule(Parser *p) +// _loop0_134: ',' (expression ['as' star_target]) +static asdl_seq * +_loop0_134_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40359,55 +33718,74 @@ _tmp_240_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // ':' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' - ) - { - D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; } - { // '}' + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // ',' (expression ['as' star_target]) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_240[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expression ['as' star_target])")); Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 26)) // token='}' + void *elem; + while ( + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = _tmp_166_rule(p)) // expression ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_240[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); - _res = _literal; - goto done; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_240[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expression ['as' star_target])")); } - _res = NULL; - done: + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); p->level--; - return _res; + return _seq; } -// _tmp_241: '!' NAME -static void * -_tmp_241_rule(Parser *p) +// _gather_135: (expression ['as' star_target]) _loop0_134 +static asdl_seq * +_gather_135_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40416,29 +33794,29 @@ _tmp_241_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - { // '!' NAME + { // (expression ['as' star_target]) _loop0_134 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_241[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); - Token * _literal; - expr_ty name_var; + D(fprintf(stderr, "%*c> _gather_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_134")); + void *elem; + asdl_seq * seq; if ( - (_literal = _PyPegen_expect_token(p, 54)) // token='!' + (elem = _tmp_166_rule(p)) // expression ['as' star_target] && - (name_var = _PyPegen_name_token(p)) // NAME + (seq = _loop0_134_rule(p)) // _loop0_134 ) { - D(fprintf(stderr, "%*c+ _tmp_241[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); - _res = _PyPegen_dummy_name(p, _literal, name_var); + D(fprintf(stderr, "%*c+ _gather_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expression ['as' star_target]) _loop0_134")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_241[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c%s _gather_135[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expression ['as' star_target]) _loop0_134")); } _res = NULL; done: @@ -40446,9 +33824,9 @@ _tmp_241_rule(Parser *p) return _res; } -// _loop0_242: fstring_format_spec +// _loop0_136: ',' (expressions ['as' star_target]) static asdl_seq * -_loop0_242_rule(Parser *p) +_loop0_136_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40468,18 +33846,27 @@ _loop0_242_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // fstring_format_spec + { // ',' (expressions ['as' star_target]) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_242[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring_format_spec")); - expr_ty fstring_format_spec_var; + D(fprintf(stderr, "%*c> _loop0_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (expressions ['as' star_target])")); + Token * _literal; + void *elem; while ( - (fstring_format_spec_var = fstring_format_spec_rule(p)) // fstring_format_spec + (_literal = _PyPegen_expect_token(p, 12)) // token=',' + && + (elem = _tmp_167_rule(p)) // expressions ['as' star_target] ) { - _res = fstring_format_spec_var; + _res = elem; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + PyMem_Free(_children); + p->level--; + return NULL; + } if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -40496,8 +33883,8 @@ _loop0_242_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_242[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring_format_spec")); + D(fprintf(stderr, "%*c%s _loop0_136[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (expressions ['as' star_target])")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -40513,9 +33900,9 @@ _loop0_242_rule(Parser *p) return _seq; } -// _tmp_243: '!' NAME -static void * -_tmp_243_rule(Parser *p) +// _gather_137: (expressions ['as' star_target]) _loop0_136 +static asdl_seq * +_gather_137_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40524,29 +33911,29 @@ _tmp_243_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + asdl_seq * _res = NULL; int _mark = p->mark; - { // '!' NAME + { // (expressions ['as' star_target]) _loop0_136 if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_243[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); - Token * _literal; - expr_ty name_var; + D(fprintf(stderr, "%*c> _gather_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_136")); + void *elem; + asdl_seq * seq; if ( - (_literal = _PyPegen_expect_token(p, 54)) // token='!' + (elem = _tmp_167_rule(p)) // expressions ['as' star_target] && - (name_var = _PyPegen_name_token(p)) // NAME + (seq = _loop0_136_rule(p)) // _loop0_136 ) { - D(fprintf(stderr, "%*c+ _tmp_243[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); - _res = _PyPegen_dummy_name(p, _literal, name_var); + D(fprintf(stderr, "%*c+ _gather_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(expressions ['as' star_target]) _loop0_136")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_243[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); + D(fprintf(stderr, "%*c%s _gather_137[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(expressions ['as' star_target]) _loop0_136")); } _res = NULL; done: @@ -40554,9 +33941,9 @@ _tmp_243_rule(Parser *p) return _res; } -// _tmp_244: ':' | '}' +// _tmp_138: 'except' | 'finally' static void * -_tmp_244_rule(Parser *p) +_tmp_138_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40567,43 +33954,43 @@ _tmp_244_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ':' + { // 'except' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'except'")); + Token * _keyword; if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' + (_keyword = _PyPegen_expect_token(p, 663)) // token='except' ) { - D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'except'")); + _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'except'")); } - { // '}' + { // 'finally' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_244[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'finally'")); + Token * _keyword; if ( - (_literal = _PyPegen_expect_token(p, 26)) // token='}' + (_keyword = _PyPegen_expect_token(p, 659)) // token='finally' ) { - D(fprintf(stderr, "%*c+ _tmp_244[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'finally'")); + _res = _keyword; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_244[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'finally'")); } _res = NULL; done: @@ -40611,9 +33998,9 @@ _tmp_244_rule(Parser *p) return _res; } -// _tmp_245: '+' | '-' | '*' | '/' | '%' | '//' | '@' -static void * -_tmp_245_rule(Parser *p) +// _loop0_139: block +static asdl_seq * +_loop0_139_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40622,140 +34009,97 @@ _tmp_245_rule(Parser *p) p->level--; return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // '+' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 14)) // token='+' - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); - } - { // '-' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 15)) // token='-' - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; } - { // '*' + Py_ssize_t _children_capacity = 1; + Py_ssize_t _n = 0; + { // block if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 16)) // token='*' + D(fprintf(stderr, "%*c> _loop0_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "block")); + asdl_stmt_seq* block_var; + while ( + (block_var = block_rule(p)) // block ) { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); - _res = _literal; - goto done; + _res = block_var; + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); + D(fprintf(stderr, "%*c%s _loop0_139[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "block")); } - { // '/' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 17)) // token='/' - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); + asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + p->level--; + return NULL; } - { // '%' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 24)) // token='%' - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'%'")); + for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); + PyMem_Free(_children); + p->level--; + return _seq; +} + +// _tmp_140: expression ['as' NAME] +static void * +_tmp_140_rule(Parser *p) +{ + if (p->level++ == MAXSTACK) { + _Pypegen_stack_overflow(p); } - { // '//' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 47)) // token='//' - ) - { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'//'")); + if (p->error_indicator) { + p->level--; + return NULL; } - { // '@' + void * _res = NULL; + int _mark = p->mark; + { // expression ['as' NAME] if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_245[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + expr_ty expression_var; if ( - (_literal = _PyPegen_expect_token(p, 49)) // token='@' + (expression_var = expression_rule(p)) // expression + && + (_opt_var = _tmp_22_rule(p), !p->error_indicator) // ['as' NAME] ) { - D(fprintf(stderr, "%*c+ _tmp_245[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' NAME]")); + _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_245[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); + D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' NAME]")); } _res = NULL; done: @@ -40763,9 +34107,9 @@ _tmp_245_rule(Parser *p) return _res; } -// _tmp_246: '+' | '-' | '~' +// _tmp_141: NEWLINE | ':' static void * -_tmp_246_rule(Parser *p) +_tmp_141_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40776,62 +34120,43 @@ _tmp_246_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '+' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); - Token * _literal; - if ( - (_literal = _PyPegen_expect_token(p, 14)) // token='+' - ) - { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); - _res = _literal; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); - } - { // '-' + { // NEWLINE if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + Token * newline_var; if ( - (_literal = _PyPegen_expect_token(p, 15)) // token='-' + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "NEWLINE")); + _res = newline_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NEWLINE")); } - { // '~' + { // ':' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_246[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 31)) // token='~' + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_246[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_246[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'~'")); + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } _res = NULL; done: @@ -40839,9 +34164,9 @@ _tmp_246_rule(Parser *p) return _res; } -// _tmp_247: star_targets '=' +// _tmp_142: positional_patterns ',' static void * -_tmp_247_rule(Parser *p) +_tmp_142_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40852,32 +34177,27 @@ _tmp_247_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // star_targets '=' + { // positional_patterns ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_247[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); Token * _literal; - expr_ty z; + asdl_pattern_seq* positional_patterns_var; if ( - (z = star_targets_rule(p)) // star_targets + (positional_patterns_var = positional_patterns_rule(p)) // positional_patterns && - (_literal = _PyPegen_expect_token(p, 22)) // token='=' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_247[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); - _res = z; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "positional_patterns ','")); + _res = _PyPegen_dummy_name(p, positional_patterns_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_247[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "positional_patterns ','")); } _res = NULL; done: @@ -40885,9 +34205,9 @@ _tmp_247_rule(Parser *p) return _res; } -// _tmp_248: '.' | '...' +// _tmp_143: '}' | ',' static void * -_tmp_248_rule(Parser *p) +_tmp_143_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40898,43 +34218,43 @@ _tmp_248_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '.' + { // '}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 23)) // token='.' + (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } - { // '...' + { // ',' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_248[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 52)) // token='...' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' ) { - D(fprintf(stderr, "%*c+ _tmp_248[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_248[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','")); } _res = NULL; done: @@ -40942,9 +34262,9 @@ _tmp_248_rule(Parser *p) return _res; } -// _tmp_249: '.' | '...' +// _tmp_144: '=' | '!' | ':' | '}' static void * -_tmp_249_rule(Parser *p) +_tmp_144_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -40955,138 +34275,81 @@ _tmp_249_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // '.' + { // '=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'='")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 23)) // token='.' + (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'='")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'='")); } - { // '...' + { // '!' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_249[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; if ( - (_literal = _PyPegen_expect_token(p, 52)) // token='...' + (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_249[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_249[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_250: '@' named_expression NEWLINE -static void * -_tmp_250_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } - void * _res = NULL; - int _mark = p->mark; - { // '@' named_expression NEWLINE + { // ':' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_250[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; - expr_ty f; - Token * newline_var; if ( - (_literal = _PyPegen_expect_token(p, 49)) // token='@' - && - (f = named_expression_rule(p)) // named_expression - && - (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_250[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); - _res = f; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_250[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_251: ',' expression -static void * -_tmp_251_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - void * _res = NULL; - int _mark = p->mark; - { // ',' expression + { // '}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_251[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); Token * _literal; - expr_ty c; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (c = expression_rule(p)) // expression + (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_251[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); - _res = c; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_251[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; done: @@ -41094,9 +34357,9 @@ _tmp_251_rule(Parser *p) return _res; } -// _tmp_252: ',' star_expression +// _tmp_145: '!' | ':' | '}' static void * -_tmp_252_rule(Parser *p) +_tmp_145_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41107,78 +34370,62 @@ _tmp_252_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ',' star_expression + { // '!' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_252[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!'")); Token * _literal; - expr_ty c; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (c = star_expression_rule(p)) // star_expression + (_literal = _PyPegen_expect_token(p, 54)) // token='!' ) { - D(fprintf(stderr, "%*c+ _tmp_252[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); - _res = c; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_252[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_253: 'or' conjunction -static void * -_tmp_253_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!'")); } - if (p->error_indicator) { - p->level--; - return NULL; + { // ':' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 11)) // token=':' + ) + { + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - void * _res = NULL; - int _mark = p->mark; - { // 'or' conjunction + { // '}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_253[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); - Token * _keyword; - expr_ty c; + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 581)) // token='or' - && - (c = conjunction_rule(p)) // conjunction + (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_253[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); - _res = c; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_253[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; done: @@ -41186,9 +34433,9 @@ _tmp_253_rule(Parser *p) return _res; } -// _tmp_254: 'and' inversion +// _tmp_146: '!' NAME static void * -_tmp_254_rule(Parser *p) +_tmp_146_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41199,32 +34446,27 @@ _tmp_254_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'and' inversion + { // '!' NAME if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_254[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); - Token * _keyword; - expr_ty c; + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + Token * _literal; + expr_ty name_var; if ( - (_keyword = _PyPegen_expect_token(p, 582)) // token='and' + (_literal = _PyPegen_expect_token(p, 54)) // token='!' && - (c = inversion_rule(p)) // inversion + (name_var = _PyPegen_name_token(p)) // NAME ) { - D(fprintf(stderr, "%*c+ _tmp_254[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); - _res = c; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!' NAME")); + _res = _PyPegen_dummy_name(p, _literal, name_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_254[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'!' NAME")); } _res = NULL; done: @@ -41232,9 +34474,9 @@ _tmp_254_rule(Parser *p) return _res; } -// _tmp_255: slice | starred_expression +// _tmp_147: ':' | '}' static void * -_tmp_255_rule(Parser *p) +_tmp_147_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41245,43 +34487,43 @@ _tmp_255_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // slice + { // ':' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); - expr_ty slice_var; + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + Token * _literal; if ( - (slice_var = slice_rule(p)) // slice + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); - _res = slice_var; + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice")); + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - { // starred_expression + { // '}' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_255[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); - expr_ty starred_expression_var; + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'}'")); + Token * _literal; if ( - (starred_expression_var = starred_expression_rule(p)) // starred_expression + (_literal = _PyPegen_expect_token(p, 26)) // token='}' ) { - D(fprintf(stderr, "%*c+ _tmp_255[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); - _res = starred_expression_var; + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'}'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_255[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'}'")); } _res = NULL; done: @@ -41289,9 +34531,9 @@ _tmp_255_rule(Parser *p) return _res; } -// _tmp_256: fstring | string +// _tmp_148: '+' | '-' | '*' | '/' | '%' | '//' | '@' static void * -_tmp_256_rule(Parser *p) +_tmp_148_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41302,135 +34544,138 @@ _tmp_256_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // fstring + { // '+' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); - expr_ty fstring_var; + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + Token * _literal; if ( - (fstring_var = fstring_rule(p)) // fstring + (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); - _res = fstring_var; + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring")); + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } - { // string + { // '-' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_256[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); - expr_ty string_var; + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + Token * _literal; if ( - (string_var = string_rule(p)) // string + (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_256[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); - _res = string_var; + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_256[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "string")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_257: 'if' disjunction -static void * -_tmp_257_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); } - if (p->error_indicator) { - p->level--; - return NULL; + { // '*' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 16)) // token='*' + ) + { + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*'")); } - void * _res = NULL; - int _mark = p->mark; - { // 'if' disjunction + { // '/' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_257[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); - Token * _keyword; - expr_ty z; + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'/'")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='if' - && - (z = disjunction_rule(p)) // disjunction + (_literal = _PyPegen_expect_token(p, 17)) // token='/' ) { - D(fprintf(stderr, "%*c+ _tmp_257[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); - _res = z; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'/'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_257[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'/'")); } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_258: 'if' disjunction -static void * -_tmp_258_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); + { // '%' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'%'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 24)) // token='%' + ) + { + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'%'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'%'")); } - if (p->error_indicator) { - p->level--; - return NULL; + { // '//' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'//'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 47)) // token='//' + ) + { + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'//'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'//'")); } - void * _res = NULL; - int _mark = p->mark; - { // 'if' disjunction + { // '@' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_258[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); - Token * _keyword; - expr_ty z; + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@'")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 668)) // token='if' - && - (z = disjunction_rule(p)) // disjunction + (_literal = _PyPegen_expect_token(p, 49)) // token='@' ) { - D(fprintf(stderr, "%*c+ _tmp_258[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); - _res = z; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_258[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@'")); } _res = NULL; done: @@ -41438,9 +34683,9 @@ _tmp_258_rule(Parser *p) return _res; } -// _tmp_259: starred_expression | (assignment_expression | expression !':=') !'=' +// _tmp_149: '+' | '-' | '~' static void * -_tmp_259_rule(Parser *p) +_tmp_149_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41451,45 +34696,62 @@ _tmp_259_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // starred_expression + { // '+' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); - expr_ty starred_expression_var; + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'+'")); + Token * _literal; if ( - (starred_expression_var = starred_expression_rule(p)) // starred_expression + (_literal = _PyPegen_expect_token(p, 14)) // token='+' ) { - D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); - _res = starred_expression_var; + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'+'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'+'")); } - { // (assignment_expression | expression !':=') !'=' + { // '-' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_259[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_274_var; + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'-'")); + Token * _literal; if ( - (_tmp_274_var = _tmp_274_rule(p)) // assignment_expression | expression !':=' - && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' + (_literal = _PyPegen_expect_token(p, 15)) // token='-' ) { - D(fprintf(stderr, "%*c+ _tmp_259[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_274_var; + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'-'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_259[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'-'")); + } + { // '~' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'~'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 31)) // token='~' + ) + { + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'~'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'~'")); } _res = NULL; done: @@ -41497,9 +34759,9 @@ _tmp_259_rule(Parser *p) return _res; } -// _tmp_260: ',' star_target +// _tmp_150: star_targets '=' static void * -_tmp_260_rule(Parser *p) +_tmp_150_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41510,22 +34772,22 @@ _tmp_260_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ',' star_target + { // star_targets '=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_260[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; - expr_ty c; + expr_ty z; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (z = star_targets_rule(p)) // star_targets && - (c = star_target_rule(p)) // star_target + (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_260[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); - _res = c; + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; p->level--; @@ -41534,8 +34796,8 @@ _tmp_260_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_260[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; done: @@ -41543,9 +34805,9 @@ _tmp_260_rule(Parser *p) return _res; } -// _tmp_261: ',' star_target +// _tmp_151: '.' | '...' static void * -_tmp_261_rule(Parser *p) +_tmp_151_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41556,32 +34818,43 @@ _tmp_261_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ',' star_target + { // '.' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_261[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; - expr_ty c; if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (c = star_target_rule(p)) // star_target + (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_261[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); - _res = c; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - p->level--; - return NULL; - } + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_261[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); + } + { // '...' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 52)) // token='...' + ) + { + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; done: @@ -41589,10 +34862,9 @@ _tmp_261_rule(Parser *p) return _res; } -// _tmp_262: -// | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs +// _tmp_152: '@' named_expression NEWLINE static void * -_tmp_262_rule(Parser *p) +_tmp_152_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41603,30 +34875,35 @@ _tmp_262_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs + { // '@' named_expression NEWLINE if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_262[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); - asdl_seq * _gather_275_var; + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; - asdl_seq* kwargs_var; + expr_ty f; + Token * newline_var; if ( - (_gather_275_var = _gather_275_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + (_literal = _PyPegen_expect_token(p, 49)) // token='@' && - (_literal = _PyPegen_expect_token(p, 12)) // token=',' + (f = named_expression_rule(p)) // named_expression && - (kwargs_var = kwargs_rule(p)) // kwargs + (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_262[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); - _res = _PyPegen_dummy_name(p, _gather_275_var, _literal, kwargs_var); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + _res = f; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_262[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; done: @@ -41634,9 +34911,9 @@ _tmp_262_rule(Parser *p) return _res; } -// _tmp_263: starred_expression !'=' +// _tmp_153: ',' star_expression static void * -_tmp_263_rule(Parser *p) +_tmp_153_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41647,26 +34924,32 @@ _tmp_263_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // starred_expression !'=' + { // ',' star_expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_263[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); - expr_ty starred_expression_var; + D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + Token * _literal; + expr_ty c; if ( - (starred_expression_var = starred_expression_rule(p)) // starred_expression + (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' + (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_263[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); - _res = starred_expression_var; + D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + _res = c; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_263[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression !'='")); + D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; done: @@ -41674,9 +34957,9 @@ _tmp_263_rule(Parser *p) return _res; } -// _tmp_264: star_targets '=' +// _tmp_154: 'or' conjunction static void * -_tmp_264_rule(Parser *p) +_tmp_154_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41687,27 +34970,32 @@ _tmp_264_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // star_targets '=' + { // 'or' conjunction if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_264[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); - Token * _literal; - expr_ty star_targets_var; + D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + Token * _keyword; + expr_ty c; if ( - (star_targets_var = star_targets_rule(p)) // star_targets + (_keyword = _PyPegen_expect_token(p, 581)) // token='or' && - (_literal = _PyPegen_expect_token(p, 22)) // token='=' + (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_264[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); - _res = _PyPegen_dummy_name(p, star_targets_var, _literal); + D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + _res = c; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_264[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; done: @@ -41715,9 +35003,9 @@ _tmp_264_rule(Parser *p) return _res; } -// _tmp_265: star_targets '=' +// _tmp_155: 'and' inversion static void * -_tmp_265_rule(Parser *p) +_tmp_155_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41728,27 +35016,32 @@ _tmp_265_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // star_targets '=' + { // 'and' inversion if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_265[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); - Token * _literal; - expr_ty star_targets_var; + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + Token * _keyword; + expr_ty c; if ( - (star_targets_var = star_targets_rule(p)) // star_targets + (_keyword = _PyPegen_expect_token(p, 582)) // token='and' && - (_literal = _PyPegen_expect_token(p, 22)) // token='=' + (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_265[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); - _res = _PyPegen_dummy_name(p, star_targets_var, _literal); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + _res = c; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_265[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; done: @@ -41756,9 +35049,9 @@ _tmp_265_rule(Parser *p) return _res; } -// _tmp_266: ')' | '**' +// _tmp_156: slice | starred_expression static void * -_tmp_266_rule(Parser *p) +_tmp_156_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41769,43 +35062,43 @@ _tmp_266_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ')' + { // slice if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slice")); + expr_ty slice_var; if ( - (_literal = _PyPegen_expect_token(p, 8)) // token=')' + (slice_var = slice_rule(p)) // slice ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slice")); + _res = slice_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slice")); } - { // '**' + { // starred_expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_266[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + expr_ty starred_expression_var; if ( - (_literal = _PyPegen_expect_token(p, 35)) // token='**' + (starred_expression_var = starred_expression_rule(p)) // starred_expression ) { - D(fprintf(stderr, "%*c+ _tmp_266[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_266[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); } _res = NULL; done: @@ -41813,9 +35106,9 @@ _tmp_266_rule(Parser *p) return _res; } -// _tmp_267: ':' | '**' +// _tmp_157: fstring | string static void * -_tmp_267_rule(Parser *p) +_tmp_157_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41826,43 +35119,43 @@ _tmp_267_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ':' + { // fstring if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "fstring")); + expr_ty fstring_var; if ( - (_literal = _PyPegen_expect_token(p, 11)) // token=':' + (fstring_var = fstring_rule(p)) // fstring ) { - D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "fstring")); + _res = fstring_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "fstring")); } - { // '**' + { // string if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_267[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); - Token * _literal; + D(fprintf(stderr, "%*c> _tmp_157[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "string")); + expr_ty string_var; if ( - (_literal = _PyPegen_expect_token(p, 35)) // token='**' + (string_var = string_rule(p)) // string ) { - D(fprintf(stderr, "%*c+ _tmp_267[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); - _res = _literal; + D(fprintf(stderr, "%*c+ _tmp_157[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "string")); + _res = string_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_267[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c%s _tmp_157[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "string")); } _res = NULL; done: @@ -41870,9 +35163,9 @@ _tmp_267_rule(Parser *p) return _res; } -// _loop0_268: (',' bitwise_or) -static asdl_seq * -_loop0_268_rule(Parser *p) +// _tmp_158: 'if' disjunction +static void * +_tmp_158_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41881,65 +35174,44 @@ _loop0_268_rule(Parser *p) p->level--; return NULL; } - void *_res = NULL; + void * _res = NULL; int _mark = p->mark; - void **_children = PyMem_Malloc(sizeof(void *)); - if (!_children) { - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - Py_ssize_t _children_capacity = 1; - Py_ssize_t _n = 0; - { // (',' bitwise_or) + { // 'if' disjunction if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_268[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); - void *_tmp_277_var; - while ( - (_tmp_277_var = _tmp_277_rule(p)) // ',' bitwise_or + D(fprintf(stderr, "%*c> _tmp_158[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + Token * _keyword; + expr_ty z; + if ( + (_keyword = _PyPegen_expect_token(p, 668)) // token='if' + && + (z = disjunction_rule(p)) // disjunction ) { - _res = _tmp_277_var; - if (_n == _children_capacity) { - _children_capacity *= 2; - void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); - if (!_new_children) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; - } - _children = _new_children; + D(fprintf(stderr, "%*c+ _tmp_158[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + _res = z; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; } - _children[_n++] = _res; - _mark = p->mark; + goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_268[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' bitwise_or)")); - } - asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); - if (!_seq) { - PyMem_Free(_children); - p->error_indicator = 1; - PyErr_NoMemory(); - p->level--; - return NULL; + D(fprintf(stderr, "%*c%s _tmp_158[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } - for (Py_ssize_t i = 0; i < _n; i++) asdl_seq_SET_UNTYPED(_seq, i, _children[i]); - PyMem_Free(_children); + _res = NULL; + done: p->level--; - return _seq; + return _res; } -// _tmp_269: expression ['as' star_target] +// _tmp_159: starred_expression | (assignment_expression | expression !':=') !'=' static void * -_tmp_269_rule(Parser *p) +_tmp_159_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41950,28 +35222,45 @@ _tmp_269_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // expression ['as' star_target] + { // starred_expression if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_269[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - expr_ty expression_var; + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + expr_ty starred_expression_var; if ( - (expression_var = expression_rule(p)) // expression + (starred_expression_var = starred_expression_rule(p)) // starred_expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + _res = starred_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); + } + { // (assignment_expression | expression !':=') !'=' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_159[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + void *_tmp_85_var; + if ( + (_tmp_85_var = _tmp_85_rule(p)) // assignment_expression | expression !':=' && - (_opt_var = _tmp_278_rule(p), !p->error_indicator) // ['as' star_target] + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_269[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); - _res = _PyPegen_dummy_name(p, expression_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_159[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); + _res = _tmp_85_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_269[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c%s _tmp_159[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); } _res = NULL; done: @@ -41979,9 +35268,9 @@ _tmp_269_rule(Parser *p) return _res; } -// _tmp_270: expressions ['as' star_target] +// _tmp_160: ',' star_target static void * -_tmp_270_rule(Parser *p) +_tmp_160_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -41992,28 +35281,32 @@ _tmp_270_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // expressions ['as' star_target] + { // ',' star_target if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_270[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - expr_ty expressions_var; + D(fprintf(stderr, "%*c> _tmp_160[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + Token * _literal; + expr_ty c; if ( - (expressions_var = expressions_rule(p)) // expressions + (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_279_rule(p), !p->error_indicator) // ['as' star_target] + (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_270[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); - _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_160[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + _res = c; + if (_res == NULL && PyErr_Occurred()) { + p->error_indicator = 1; + p->level--; + return NULL; + } goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_270[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c%s _tmp_160[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; done: @@ -42021,9 +35314,10 @@ _tmp_270_rule(Parser *p) return _res; } -// _tmp_271: expression ['as' star_target] +// _tmp_161: +// | ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs static void * -_tmp_271_rule(Parser *p) +_tmp_161_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42034,28 +35328,30 @@ _tmp_271_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // expression ['as' star_target] + { // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_271[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - expr_ty expression_var; + D(fprintf(stderr, "%*c> _tmp_161[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + asdl_seq * _gather_87_var; + Token * _literal; + asdl_seq* kwargs_var; if ( - (expression_var = expression_rule(p)) // expression + (_gather_87_var = _gather_87_rule(p)) // ','.(starred_expression | (assignment_expression | expression !':=') !'=')+ + && + (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_280_rule(p), !p->error_indicator) // ['as' star_target] + (kwargs_var = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_271[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); - _res = _PyPegen_dummy_name(p, expression_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_161[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); + _res = _PyPegen_dummy_name(p, _gather_87_var, _literal, kwargs_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_271[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); + D(fprintf(stderr, "%*c%s _tmp_161[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | (assignment_expression | expression !':=') !'=')+ ',' kwargs")); } _res = NULL; done: @@ -42063,9 +35359,9 @@ _tmp_271_rule(Parser *p) return _res; } -// _tmp_272: expressions ['as' star_target] +// _tmp_162: starred_expression !'=' static void * -_tmp_272_rule(Parser *p) +_tmp_162_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42076,28 +35372,26 @@ _tmp_272_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // expressions ['as' star_target] + { // starred_expression !'=' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_272[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); - void *_opt_var; - UNUSED(_opt_var); // Silence compiler warnings - expr_ty expressions_var; + D(fprintf(stderr, "%*c> _tmp_162[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); + expr_ty starred_expression_var; if ( - (expressions_var = expressions_rule(p)) // expressions + (starred_expression_var = starred_expression_rule(p)) // starred_expression && - (_opt_var = _tmp_281_rule(p), !p->error_indicator) // ['as' star_target] + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_272[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); - _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); + D(fprintf(stderr, "%*c+ _tmp_162[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression !'='")); + _res = starred_expression_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_272[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); + D(fprintf(stderr, "%*c%s _tmp_162[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression !'='")); } _res = NULL; done: @@ -42105,9 +35399,9 @@ _tmp_272_rule(Parser *p) return _res; } -// _tmp_273: 'as' NAME +// _tmp_163: ')' | '**' static void * -_tmp_273_rule(Parser *p) +_tmp_163_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42118,27 +35412,43 @@ _tmp_273_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' NAME + { // ')' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_273[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - Token * _keyword; - expr_ty name_var; + D(fprintf(stderr, "%*c> _tmp_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + Token * _literal; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' - && - (name_var = _PyPegen_name_token(p)) // NAME + (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_273[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' NAME")); - _res = _PyPegen_dummy_name(p, _keyword, name_var); + D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_273[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' NAME")); + D(fprintf(stderr, "%*c%s _tmp_163[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); + } + { // '**' + if (p->error_indicator) { + p->level--; + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_163[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + Token * _literal; + if ( + (_literal = _PyPegen_expect_token(p, 35)) // token='**' + ) + { + D(fprintf(stderr, "%*c+ _tmp_163[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + _res = _literal; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_163[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; done: @@ -42146,9 +35456,9 @@ _tmp_273_rule(Parser *p) return _res; } -// _tmp_274: assignment_expression | expression !':=' +// _tmp_164: ':' | '**' static void * -_tmp_274_rule(Parser *p) +_tmp_164_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42159,45 +35469,43 @@ _tmp_274_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // assignment_expression + { // ':' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); - expr_ty assignment_expression_var; + D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + Token * _literal; if ( - (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression + (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); - _res = assignment_expression_var; + D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); + D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } - { // expression !':=' + { // '**' if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_274[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); - expr_ty expression_var; + D(fprintf(stderr, "%*c> _tmp_164[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + Token * _literal; if ( - (expression_var = expression_rule(p)) // expression - && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' + (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_274[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); - _res = expression_var; + D(fprintf(stderr, "%*c+ _tmp_164[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_274[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); + D(fprintf(stderr, "%*c%s _tmp_164[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; done: @@ -42205,9 +35513,9 @@ _tmp_274_rule(Parser *p) return _res; } -// _loop0_276: ',' (starred_expression | (assignment_expression | expression !':=') !'=') +// _loop0_165: (',' bitwise_or) static asdl_seq * -_loop0_276_rule(Parser *p) +_loop0_165_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42227,27 +35535,18 @@ _loop0_276_rule(Parser *p) } Py_ssize_t _children_capacity = 1; Py_ssize_t _n = 0; - { // ',' (starred_expression | (assignment_expression | expression !':=') !'=') + { // (',' bitwise_or) if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _loop0_276[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); - Token * _literal; - void *elem; + D(fprintf(stderr, "%*c> _loop0_165[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' bitwise_or)")); + void *_tmp_168_var; while ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (elem = _tmp_282_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' + (_tmp_168_var = _tmp_168_rule(p)) // ',' bitwise_or ) { - _res = elem; - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - PyMem_Free(_children); - p->level--; - return NULL; - } + _res = _tmp_168_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -42264,8 +35563,8 @@ _loop0_276_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_276[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | (assignment_expression | expression !':=') !'=')")); + D(fprintf(stderr, "%*c%s _loop0_165[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' bitwise_or)")); } asdl_seq *_seq = (asdl_seq*)_Py_asdl_generic_seq_new(_n, p->arena); if (!_seq) { @@ -42281,92 +35580,9 @@ _loop0_276_rule(Parser *p) return _seq; } -// _gather_275: -// | (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_276 -static asdl_seq * -_gather_275_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - asdl_seq * _res = NULL; - int _mark = p->mark; - { // (starred_expression | (assignment_expression | expression !':=') !'=') _loop0_276 - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _gather_275[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_276")); - void *elem; - asdl_seq * seq; - if ( - (elem = _tmp_282_rule(p)) // starred_expression | (assignment_expression | expression !':=') !'=' - && - (seq = _loop0_276_rule(p)) // _loop0_276 - ) - { - D(fprintf(stderr, "%*c+ _gather_275[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_276")); - _res = _PyPegen_seq_insert_in_front(p, elem, seq); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_275[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | (assignment_expression | expression !':=') !'=') _loop0_276")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_277: ',' bitwise_or -static void * -_tmp_277_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // ',' bitwise_or - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_277[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); - Token * _literal; - expr_ty bitwise_or_var; - if ( - (_literal = _PyPegen_expect_token(p, 12)) // token=',' - && - (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or - ) - { - D(fprintf(stderr, "%*c+ _tmp_277[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); - _res = _PyPegen_dummy_name(p, _literal, bitwise_or_var); - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_277[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' bitwise_or")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_278: 'as' star_target +// _tmp_166: expression ['as' star_target] static void * -_tmp_278_rule(Parser *p) +_tmp_166_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42377,27 +35593,28 @@ _tmp_278_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' star_target + { // expression ['as' star_target] if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_278[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); - Token * _keyword; - expr_ty star_target_var; + D(fprintf(stderr, "%*c> _tmp_166[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + expr_ty expression_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' + (expression_var = expression_rule(p)) // expression && - (star_target_var = star_target_rule(p)) // star_target + (_opt_var = _tmp_169_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_278[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); - _res = _PyPegen_dummy_name(p, _keyword, star_target_var); + D(fprintf(stderr, "%*c+ _tmp_166[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression ['as' star_target]")); + _res = _PyPegen_dummy_name(p, expression_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_278[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c%s _tmp_166[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression ['as' star_target]")); } _res = NULL; done: @@ -42405,9 +35622,9 @@ _tmp_278_rule(Parser *p) return _res; } -// _tmp_279: 'as' star_target +// _tmp_167: expressions ['as' star_target] static void * -_tmp_279_rule(Parser *p) +_tmp_167_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42418,27 +35635,28 @@ _tmp_279_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' star_target + { // expressions ['as' star_target] if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_279[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); - Token * _keyword; - expr_ty star_target_var; + D(fprintf(stderr, "%*c> _tmp_167[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + void *_opt_var; + UNUSED(_opt_var); // Silence compiler warnings + expr_ty expressions_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' + (expressions_var = expressions_rule(p)) // expressions && - (star_target_var = star_target_rule(p)) // star_target + (_opt_var = _tmp_169_rule(p), !p->error_indicator) // ['as' star_target] ) { - D(fprintf(stderr, "%*c+ _tmp_279[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); - _res = _PyPegen_dummy_name(p, _keyword, star_target_var); + D(fprintf(stderr, "%*c+ _tmp_167[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expressions ['as' star_target]")); + _res = _PyPegen_dummy_name(p, expressions_var, _opt_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_279[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c%s _tmp_167[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expressions ['as' star_target]")); } _res = NULL; done: @@ -42446,9 +35664,9 @@ _tmp_279_rule(Parser *p) return _res; } -// _tmp_280: 'as' star_target +// _tmp_168: ',' bitwise_or static void * -_tmp_280_rule(Parser *p) +_tmp_168_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42459,27 +35677,27 @@ _tmp_280_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // 'as' star_target + { // ',' bitwise_or if (p->error_indicator) { p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_280[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); - Token * _keyword; - expr_ty star_target_var; + D(fprintf(stderr, "%*c> _tmp_168[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + Token * _literal; + expr_ty bitwise_or_var; if ( - (_keyword = _PyPegen_expect_token(p, 666)) // token='as' + (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (star_target_var = star_target_rule(p)) // star_target + (bitwise_or_var = bitwise_or_rule(p)) // bitwise_or ) { - D(fprintf(stderr, "%*c+ _tmp_280[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); - _res = _PyPegen_dummy_name(p, _keyword, star_target_var); + D(fprintf(stderr, "%*c+ _tmp_168[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' bitwise_or")); + _res = _PyPegen_dummy_name(p, _literal, bitwise_or_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_280[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c%s _tmp_168[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' bitwise_or")); } _res = NULL; done: @@ -42487,9 +35705,9 @@ _tmp_280_rule(Parser *p) return _res; } -// _tmp_281: 'as' star_target +// _tmp_169: 'as' star_target static void * -_tmp_281_rule(Parser *p) +_tmp_169_rule(Parser *p) { if (p->level++ == MAXSTACK) { _Pypegen_stack_overflow(p); @@ -42505,7 +35723,7 @@ _tmp_281_rule(Parser *p) p->level--; return NULL; } - D(fprintf(stderr, "%*c> _tmp_281[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c> _tmp_169[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'as' star_target")); Token * _keyword; expr_ty star_target_var; if ( @@ -42514,12 +35732,12 @@ _tmp_281_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_281[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); + D(fprintf(stderr, "%*c+ _tmp_169[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'as' star_target")); _res = _PyPegen_dummy_name(p, _keyword, star_target_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_281[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_169[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'as' star_target")); } _res = NULL; @@ -42528,124 +35746,6 @@ _tmp_281_rule(Parser *p) return _res; } -// _tmp_282: starred_expression | (assignment_expression | expression !':=') !'=' -static void * -_tmp_282_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // starred_expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_282[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); - expr_ty starred_expression_var; - if ( - (starred_expression_var = starred_expression_rule(p)) // starred_expression - ) - { - D(fprintf(stderr, "%*c+ _tmp_282[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); - _res = starred_expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_282[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); - } - { // (assignment_expression | expression !':=') !'=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_282[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - void *_tmp_283_var; - if ( - (_tmp_283_var = _tmp_283_rule(p)) // assignment_expression | expression !':=' - && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_282[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - _res = _tmp_283_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_282[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(assignment_expression | expression !':=') !'='")); - } - _res = NULL; - done: - p->level--; - return _res; -} - -// _tmp_283: assignment_expression | expression !':=' -static void * -_tmp_283_rule(Parser *p) -{ - if (p->level++ == MAXSTACK) { - _Pypegen_stack_overflow(p); - } - if (p->error_indicator) { - p->level--; - return NULL; - } - void * _res = NULL; - int _mark = p->mark; - { // assignment_expression - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_283[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "assignment_expression")); - expr_ty assignment_expression_var; - if ( - (assignment_expression_var = assignment_expression_rule(p)) // assignment_expression - ) - { - D(fprintf(stderr, "%*c+ _tmp_283[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "assignment_expression")); - _res = assignment_expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_283[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "assignment_expression")); - } - { // expression !':=' - if (p->error_indicator) { - p->level--; - return NULL; - } - D(fprintf(stderr, "%*c> _tmp_283[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression !':='")); - expr_ty expression_var; - if ( - (expression_var = expression_rule(p)) // expression - && - _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 53) // token=':=' - ) - { - D(fprintf(stderr, "%*c+ _tmp_283[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression !':='")); - _res = expression_var; - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_283[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression !':='")); - } - _res = NULL; - done: - p->level--; - return _res; -} - void * _PyPegen_parse(Parser *p) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index ab2b2d06cca15d..ab619e32429d63 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -311,14 +311,36 @@ static int test_pre_initialization_api(void) _Py_EMBED_PREINIT_CHECK("Checking Py_SetProgramName\n"); Py_SetProgramName(program); + _Py_EMBED_PREINIT_CHECK("Checking !Py_IsInitialized pre-initialization\n"); + if (Py_IsInitialized()) { + fprintf(stderr, "Fatal error: initialized before initialization!\n"); + return 1; + } + _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n"); Py_Initialize(); + + _Py_EMBED_PREINIT_CHECK("Checking Py_IsInitialized post-initialization\n"); + if (!Py_IsInitialized()) { + fprintf(stderr, "Fatal error: not initialized after initialization!\n"); + return 1; + } + _Py_EMBED_PREINIT_CHECK("Check sys module contents\n"); - PyRun_SimpleString("import sys; " - "print('sys.executable:', sys.executable)"); + PyRun_SimpleString( + "import sys; " + "print('sys.executable:', sys.executable); " + "sys.stdout.flush(); " + ); _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n"); Py_Finalize(); + _Py_EMBED_PREINIT_CHECK("Checking !Py_IsInitialized post-finalization\n"); + if (Py_IsInitialized()) { + fprintf(stderr, "Fatal error: still initialized after finalization!\n"); + return 1; + } + _Py_EMBED_PREINIT_CHECK("Freeing memory allocated by Py_DecodeLocale\n"); PyMem_RawFree(program); return 0; @@ -364,12 +386,15 @@ static int test_pre_initialization_sys_options(void) _Py_EMBED_PREINIT_CHECK("Initializing interpreter\n"); _testembed_Py_InitializeFromConfig(); _Py_EMBED_PREINIT_CHECK("Check sys module contents\n"); - PyRun_SimpleString("import sys; " - "print('sys.warnoptions:', sys.warnoptions); " - "print('sys._xoptions:', sys._xoptions); " - "warnings = sys.modules['warnings']; " - "latest_filters = [f[0] for f in warnings.filters[:3]]; " - "print('warnings.filters[:3]:', latest_filters)"); + PyRun_SimpleString( + "import sys; " + "print('sys.warnoptions:', sys.warnoptions); " + "print('sys._xoptions:', sys._xoptions); " + "warnings = sys.modules['warnings']; " + "latest_filters = [f[0] for f in warnings.filters[:3]]; " + "print('warnings.filters[:3]:', latest_filters); " + "sys.stdout.flush(); " + ); _Py_EMBED_PREINIT_CHECK("Finalizing interpreter\n"); Py_Finalize(); diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 860447ef9ed702..89c52b9dc73cac 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -19,7 +19,7 @@ struct validator { }; // Forward declaration -static int init_types(struct ast_state *state); +static int init_types(void *arg); static struct ast_state* get_ast_state(void) @@ -5044,8 +5044,9 @@ typedef struct { } AST_object; static void -ast_dealloc(AST_object *self) +ast_dealloc(PyObject *op) { + AST_object *self = (AST_object*)op; /* bpo-31095: UnTrack is needed before calling any callbacks */ PyTypeObject *tp = Py_TYPE(self); PyObject_GC_UnTrack(self); @@ -5057,16 +5058,18 @@ ast_dealloc(AST_object *self) } static int -ast_traverse(AST_object *self, visitproc visit, void *arg) +ast_traverse(PyObject *op, visitproc visit, void *arg) { + AST_object *self = (AST_object*)op; Py_VISIT(Py_TYPE(self)); Py_VISIT(self->dict); return 0; } static int -ast_clear(AST_object *self) +ast_clear(PyObject *op) { + AST_object *self = (AST_object*)op; Py_CLEAR(self->dict); return 0; } @@ -5806,7 +5809,6 @@ ast_repr_max_depth(AST_object *self, int depth) if (!value_repr) { Py_DECREF(name); - Py_DECREF(value); goto error; } @@ -5852,9 +5854,9 @@ ast_repr_max_depth(AST_object *self, int depth) } static PyObject * -ast_repr(AST_object *self) +ast_repr(PyObject *self) { - return ast_repr_max_depth(self, 3); + return ast_repr_max_depth((AST_object*)self, 3); } static PyType_Slot AST_type_slots[] = { @@ -6047,8 +6049,9 @@ static int add_ast_fields(struct ast_state *state) static int -init_types(struct ast_state *state) +init_types(void *arg) { + struct ast_state *state = arg; if (init_identifiers(state) < 0) { return -1; } diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8535306d9c7a03..228d82173e6126 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -149,7 +149,7 @@ dummy_func( op(_CHECK_PERIODIC, (--)) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { int err = _Py_HandlePending(tstate); ERROR_IF(err != 0, error); @@ -207,10 +207,8 @@ dummy_func( } op(_MONITOR_RESUME, (--)) { - _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation( tstate, oparg > 0, frame, this_instr); - stack_pointer = _PyFrame_GetStackPointer(frame); ERROR_IF(err, error); if (frame->instr_ptr != this_instr) { /* Instrumentation has jumped */ @@ -263,6 +261,7 @@ dummy_func( replicate(8) inst(STORE_FAST, (value --)) { SETLOCAL(oparg, value); + DEAD(value); } pseudo(STORE_FAST_MAYBE_NULL, (unused --)) = { @@ -273,6 +272,7 @@ dummy_func( uint32_t oparg1 = oparg >> 4; uint32_t oparg2 = oparg & 15; SETLOCAL(oparg1, value1); + DEAD(value1); value2 = PyStackRef_DUP(GETLOCAL(oparg2)); } @@ -280,7 +280,9 @@ dummy_func( uint32_t oparg1 = oparg >> 4; uint32_t oparg2 = oparg & 15; SETLOCAL(oparg1, value1); + DEAD(value1); SETLOCAL(oparg2, value2); + DEAD(value2); } pure inst(POP_TOP, (value --)) { @@ -305,12 +307,14 @@ dummy_func( DECREF_INPUTS(); } - pure inst(END_SEND, (receiver, value -- value)) { + pure inst(END_SEND, (receiver, value -- val)) { (void)receiver; + val = value; + DEAD(value); PyStackRef_CLOSE(receiver); } - tier1 inst(INSTRUMENTED_END_SEND, (receiver, value -- value)) { + tier1 inst(INSTRUMENTED_END_SEND, (receiver, value -- val)) { PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value)); @@ -318,6 +322,8 @@ dummy_func( ERROR_NO_POP(); } } + val = value; + DEAD(value); PyStackRef_CLOSE(receiver); } @@ -332,6 +338,7 @@ dummy_func( assert(PyStackRef_BoolCheck(value)); res = PyStackRef_Is(value, PyStackRef_False) ? PyStackRef_True : PyStackRef_False; + DEAD(value); } family(TO_BOOL, INLINE_CACHE_ENTRIES_TO_BOOL) = { @@ -375,6 +382,7 @@ dummy_func( STAT_INC(TO_BOOL, hit); if (_PyLong_IsZero((PyLongObject *)value_o)) { assert(_Py_IsImmortalLoose(value_o)); + DEAD(value); res = PyStackRef_False; } else { @@ -394,6 +402,7 @@ dummy_func( inst(TO_BOOL_NONE, (unused/1, unused/2, value -- res)) { // This one is a bit weird, because we expect *some* failures: EXIT_IF(!PyStackRef_Is(value, PyStackRef_None)); + DEAD(value); STAT_INC(TO_BOOL, hit); res = PyStackRef_False; } @@ -404,6 +413,7 @@ dummy_func( STAT_INC(TO_BOOL, hit); if (value_o == &_Py_STR(empty)) { assert(_Py_IsImmortalLoose(value_o)); + DEAD(value); res = PyStackRef_False; } else { @@ -466,6 +476,7 @@ dummy_func( PyObject *res_o = _PyLong_Multiply((PyLongObject *)left_o, (PyLongObject *)right_o); _Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free); + INPUTS_DEAD(); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -478,6 +489,7 @@ dummy_func( PyObject *res_o = _PyLong_Add((PyLongObject *)left_o, (PyLongObject *)right_o); _Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free); _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free); + INPUTS_DEAD(); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -489,7 +501,8 @@ dummy_func( STAT_INC(BINARY_OP, hit); PyObject *res_o = _PyLong_Subtract((PyLongObject *)left_o, (PyLongObject *)right_o); _Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free);; + _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free); + INPUTS_DEAD(); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -528,6 +541,7 @@ dummy_func( ((PyFloatObject *)right_o)->ob_fval; PyObject *res_o; DECREF_INPUTS_AND_REUSE_FLOAT(left_o, right_o, dres, res_o); + INPUTS_DEAD(); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -541,6 +555,7 @@ dummy_func( ((PyFloatObject *)right_o)->ob_fval; PyObject *res_o; DECREF_INPUTS_AND_REUSE_FLOAT(left_o, right_o, dres, res_o); + INPUTS_DEAD(); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -554,6 +569,7 @@ dummy_func( ((PyFloatObject *)right_o)->ob_fval; PyObject *res_o; DECREF_INPUTS_AND_REUSE_FLOAT(left_o, right_o, dres, res_o); + INPUTS_DEAD(); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -580,6 +596,7 @@ dummy_func( PyObject *res_o = PyUnicode_Concat(left_o, right_o); _Py_DECREF_SPECIALIZED(left_o, _PyUnicode_ExactDealloc); _Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc); + INPUTS_DEAD(); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -620,10 +637,12 @@ dummy_func( */ assert(Py_REFCNT(left_o) >= 2); _Py_DECREF_NO_DEALLOC(left_o); + DEAD(left); PyObject *temp = PyStackRef_AsPyObjectBorrow(*target_local); PyUnicode_Append(&temp, right_o); *target_local = PyStackRef_FromPyObjectSteal(temp); _Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc); + DEAD(right); ERROR_IF(PyStackRef_IsNull(*target_local), error); #if TIER_ONE // The STORE_FAST is already done. This is done here in tier one, @@ -645,6 +664,7 @@ dummy_func( }; specializing op(_SPECIALIZE_BINARY_SUBSCR, (counter/1, container, sub -- container, sub)) { + assert(frame->stackpointer == NULL); #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; @@ -736,6 +756,7 @@ dummy_func( assert(res_o != NULL); Py_INCREF(res_o); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + DEAD(sub_st); PyStackRef_CLOSE(list_st); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -755,6 +776,7 @@ dummy_func( STAT_INC(BINARY_SUBSCR, hit); PyObject *res_o = (PyObject*)&_Py_SINGLETON(strings).ascii[c]; _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + DEAD(sub_st); PyStackRef_CLOSE(str_st); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -775,6 +797,7 @@ dummy_func( assert(res_o != NULL); Py_INCREF(res_o); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + DEAD(sub_st); PyStackRef_CLOSE(tuple_st); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -815,9 +838,9 @@ dummy_func( PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; PyObject *getitem = ht->_spec_cache.getitem; new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame); - SYNC_SP(); new_frame->localsplus[0] = container; new_frame->localsplus[1] = sub; + INPUTS_DEAD(); frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_BINARY_SUBSCR); } @@ -829,8 +852,9 @@ dummy_func( _PUSH_FRAME; inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) { - ERROR_IF(_PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), - PyStackRef_AsPyObjectSteal(v)) < 0, error); + int err = _PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), + PyStackRef_AsPyObjectSteal(v)); + ERROR_IF(err < 0, error); } inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) { @@ -885,6 +909,7 @@ dummy_func( assert(old_value != NULL); Py_DECREF(old_value); _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free); + DEAD(sub_st); PyStackRef_CLOSE(list_st); } @@ -928,25 +953,14 @@ dummy_func( } tier1 inst(RAISE_VARARGS, (args[oparg] -- )) { - PyObject *cause = NULL, *exc = NULL; - switch (oparg) { - case 2: - cause = PyStackRef_AsPyObjectSteal(args[1]); - _Py_FALLTHROUGH; - case 1: - exc = PyStackRef_AsPyObjectSteal(args[0]); - _Py_FALLTHROUGH; - case 0: - if (do_raise(tstate, exc, cause)) { - assert(oparg == 0); - monitor_reraise(tstate, frame, this_instr); - goto exception_unwind; - } - break; - default: - _PyErr_SetString(tstate, PyExc_SystemError, - "bad RAISE_VARARGS oparg"); - break; + assert(oparg < 3); + PyObject *cause = oparg == 2 ? PyStackRef_AsPyObjectSteal(args[1]) : NULL; + PyObject *exc = oparg > 0 ? PyStackRef_AsPyObjectSteal(args[0]) : NULL; + int err = do_raise(tstate, exc, cause); + if (err) { + assert(oparg == 0); + monitor_reraise(tstate, frame, this_instr); + goto exception_unwind; } ERROR_IF(true, error); } @@ -969,17 +983,18 @@ dummy_func( #if TIER_ONE assert(frame != &entry_frame); #endif - SYNC_SP(); - _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef temp = retval; + DEAD(retval); + SAVE_STACK(); assert(EMPTY()); _Py_LeaveRecursiveCallPy(tstate); // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); - LOAD_SP(); + RELOAD_STACK(); LOAD_IP(frame->return_offset); - res = retval; + res = temp; LLTRACE_RESUME_FRAME(); } @@ -987,7 +1002,7 @@ dummy_func( int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, this_instr, PyStackRef_AsPyObjectBorrow(val)); - if (err) ERROR_NO_POP(); + ERROR_IF(err, error); } macro(INSTRUMENTED_RETURN_VALUE) = @@ -1111,7 +1126,8 @@ dummy_func( JUMPBY(oparg); } else { - ERROR_NO_POP(); + DECREF_INPUTS(); + ERROR_IF(true, error); } } PyStackRef_CLOSE(v); @@ -1127,6 +1143,7 @@ dummy_func( STAT_INC(SEND, hit); gen_frame = &gen->gi_iframe; _PyFrame_StackPush(gen_frame, v); + DEAD(v); gen->gi_frame_state = FRAME_EXECUTING; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; @@ -1153,8 +1170,9 @@ dummy_func( assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); assert(oparg == 0 || oparg == 1); gen->gi_frame_state = FRAME_SUSPENDED + oparg; - SYNC_SP(); - _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef temp = retval; + DEAD(retval); + SAVE_STACK(); tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; _Py_LeaveRecursiveCallPy(tstate); @@ -1171,19 +1189,19 @@ dummy_func( _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); #endif + RELOAD_STACK(); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - LOAD_SP(); - value = retval; + value = temp; LLTRACE_RESUME_FRAME(); } tier1 op(_YIELD_VALUE_EVENT, (val -- val)) { - SAVE_SP(); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_YIELD, frame, this_instr, PyStackRef_AsPyObjectBorrow(val)); - LOAD_SP(); - if (err) ERROR_NO_POP(); + if (err) { + ERROR_NO_POP(); + } if (frame->instr_ptr != this_instr) { next_instr = frame->instr_ptr; DISPATCH(); @@ -1202,7 +1220,7 @@ dummy_func( } tier1 inst(RERAISE, (values[oparg], exc_st -- values[oparg])) { - PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); + PyObject *exc = PyStackRef_AsPyObjectSteal(exc_st); assert(oparg >= 0 && oparg <= 2); if (oparg) { @@ -1213,11 +1231,11 @@ dummy_func( } else { _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); + Py_DECREF(exc); ERROR_NO_POP(); } } assert(exc && PyExceptionInstance_Check(exc)); - Py_INCREF(exc); _PyErr_SetRaisedException(tstate, exc); monitor_reraise(tstate, frame, this_instr); goto exception_unwind; @@ -1227,7 +1245,8 @@ dummy_func( PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); assert(exc && PyExceptionInstance_Check(exc)); - if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { + int matches = PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration); + if (matches) { DECREF_INPUTS(); } else { @@ -1245,9 +1264,9 @@ dummy_func( int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration); if (matches) { + none = PyStackRef_None; value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value); DECREF_INPUTS(); - none = PyStackRef_None; } else { _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); @@ -1258,21 +1277,22 @@ dummy_func( inst(LOAD_COMMON_CONSTANT, ( -- value)) { // Keep in sync with _common_constants in opcode.py - switch(oparg) { - case CONSTANT_ASSERTIONERROR: - value = PyStackRef_FromPyObjectImmortal(PyExc_AssertionError); - break; - case CONSTANT_NOTIMPLEMENTEDERROR: - value = PyStackRef_FromPyObjectImmortal(PyExc_NotImplementedError); - break; - default: - Py_FatalError("bad LOAD_COMMON_CONSTANT oparg"); + // If we ever have more than two constants, use a lookup table + PyObject *val; + if (oparg == CONSTANT_ASSERTIONERROR) { + val = PyExc_AssertionError; } + else { + assert(oparg == CONSTANT_NOTIMPLEMENTEDERROR); + val = PyExc_NotImplementedError; + } + value = PyStackRef_FromPyObjectImmortal(val); } inst(LOAD_BUILD_CLASS, ( -- bc)) { PyObject *bc_o; - ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o) < 0, error); + int err = PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o); + ERROR_IF(err < 0, error); if (bc_o == NULL) { _PyErr_SetString(tstate, PyExc_NameError, "__build_class__ not found"); @@ -1291,10 +1311,12 @@ dummy_func( DECREF_INPUTS(); ERROR_IF(true, error); } - if (PyDict_CheckExact(ns)) + if (PyDict_CheckExact(ns)) { err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); - else + } + else { err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + } DECREF_INPUTS(); ERROR_IF(err, error); } @@ -1460,9 +1482,8 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *v_o; int err = PyMapping_GetOptionalItem(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &v_o); - if (err < 0) { - ERROR_NO_POP(); - } + DECREF_INPUTS(); + ERROR_IF(err < 0, error); if (v_o == NULL) { if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) @@ -1483,10 +1504,12 @@ dummy_func( else { /* Slow-path if globals or builtins is not a dict */ /* namespace 1: globals */ - ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &v_o) < 0, error); + int err = PyMapping_GetOptionalItem(GLOBALS(), name, &v_o); + ERROR_IF(err < 0, error); if (v_o == NULL) { /* namespace 2: builtins */ - ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0, error); + int err = PyMapping_GetOptionalItem(BUILTINS(), name, &v_o); + ERROR_IF(err < 0, error); if (v_o == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, @@ -1496,7 +1519,6 @@ dummy_func( } } } - DECREF_INPUTS(); v = PyStackRef_FromPyObjectSteal(v_o); } @@ -1691,12 +1713,14 @@ dummy_func( inst(BUILD_TUPLE, (values[oparg] -- tup)) { PyObject *tup_o = _PyTuple_FromStackRefSteal(values, oparg); + INPUTS_DEAD(); ERROR_IF(tup_o == NULL, error); tup = PyStackRef_FromPyObjectSteal(tup_o); } inst(BUILD_LIST, (values[oparg] -- list)) { PyObject *list_o = _PyList_FromStackRefSteal(values, oparg); + INPUTS_DEAD(); ERROR_IF(list_o == NULL, error); list = PyStackRef_FromPyObjectSteal(list_o); } @@ -1743,6 +1767,7 @@ dummy_func( } PyStackRef_CLOSE(values[i]); } + DEAD(values); if (err != 0) { Py_DECREF(set_o); ERROR_IF(true, error); @@ -1767,7 +1792,6 @@ dummy_func( } inst(SETUP_ANNOTATIONS, (--)) { - int err; PyObject *ann_dict; if (LOCALS() == NULL) { _PyErr_Format(tstate, PyExc_SystemError, @@ -1775,7 +1799,8 @@ dummy_func( ERROR_IF(true, error); } /* check if __annotations__ in locals()... */ - ERROR_IF(PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0, error); + int err = PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict); + ERROR_IF(err < 0, error); if (ann_dict == NULL) { ann_dict = PyDict_New(); ERROR_IF(ann_dict == NULL, error); @@ -1869,7 +1894,10 @@ dummy_func( int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, global_super, arg); - ERROR_IF(err, error); + if (err) { + DECREF_INPUTS(); + ERROR_IF(true, error); + } } // we make no attempt to optimize here; specializations should // handle any case whose performance we care about @@ -1894,9 +1922,10 @@ dummy_func( DECREF_INPUTS(); ERROR_IF(super == NULL, error); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - attr = PyStackRef_FromPyObjectSteal(PyObject_GetAttr(super, name)); + PyObject *attr_o = PyObject_GetAttr(super, name); Py_DECREF(super); - ERROR_IF(PyStackRef_IsNull(attr), error); + ERROR_IF(attr_o == NULL, error); + attr = PyStackRef_FromPyObjectSteal(attr_o); null = PyStackRef_NULL; } @@ -1940,6 +1969,7 @@ dummy_func( } if (method_found) { self_or_null = self_st; // transfer ownership + DEAD(self_st); } else { PyStackRef_CLOSE(self_st); self_or_null = PyStackRef_NULL; @@ -1991,6 +2021,7 @@ dummy_func( */ assert(attr_o != NULL); // No errors on this branch self_or_null = owner; // Transfer ownership + DEAD(owner); } else { /* meth is not an unbound method (but a regular attr, or @@ -2009,6 +2040,8 @@ dummy_func( attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); DECREF_INPUTS(); ERROR_IF(attr_o == NULL, error); + /* We need to define self_or_null on all paths */ + self_or_null = PyStackRef_NULL; } attr = PyStackRef_FromPyObjectSteal(attr_o); } @@ -2172,6 +2205,7 @@ dummy_func( STAT_INC(LOAD_ATTR, hit); new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); new_frame->localsplus[0] = owner; + DEAD(owner); } macro(LOAD_ATTR_PROPERTY) = @@ -2206,6 +2240,7 @@ dummy_func( // Manipulate stack directly because we exit with DISPATCH_INLINED(). STACK_SHRINK(1); new_frame->localsplus[0] = owner; + DEAD(owner); new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); @@ -2254,7 +2289,6 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries); PyObject *old_value; - uint64_t new_version; DEOPT_IF(!DK_IS_UNICODE(dict->ma_keys)); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; DEOPT_IF(ep->me_key != name); @@ -2264,9 +2298,8 @@ dummy_func( } old_value = ep->me_value; PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED; - new_version = _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value)); + _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value)); ep->me_value = PyStackRef_AsPyObjectSteal(value); - dict->ma_version_tag = new_version; // PEP 509 // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault, // when dict only holds the strong reference to value in ep->me_value. Py_XDECREF(old_value); @@ -2353,7 +2386,9 @@ dummy_func( // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg int sign_ish = COMPARISON_BIT(dleft, dright); _Py_DECREF_SPECIALIZED(left_o, _PyFloat_ExactDealloc); + DEAD(left); _Py_DECREF_SPECIALIZED(right_o, _PyFloat_ExactDealloc); + DEAD(right); res = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False; // It's always a bool, so we don't care about oparg & 16. } @@ -2373,7 +2408,9 @@ dummy_func( // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg int sign_ish = COMPARISON_BIT(ileft, iright); _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free); + DEAD(left); _Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free); + DEAD(right); res = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False; // It's always a bool, so we don't care about oparg & 16. } @@ -2387,7 +2424,9 @@ dummy_func( int eq = _PyUnicode_Equal(left_o, right_o); assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE); _Py_DECREF_SPECIALIZED(left_o, _PyUnicode_ExactDealloc); + DEAD(left); _Py_DECREF_SPECIALIZED(right_o, _PyUnicode_ExactDealloc); + DEAD(right); assert(eq == 0 || eq == 1); assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); @@ -2609,6 +2648,7 @@ dummy_func( replaced op(_POP_JUMP_IF_FALSE, (cond -- )) { assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_Is(cond, PyStackRef_False); + DEAD(cond); #if ENABLE_SPECIALIZATION this_instr[1].cache = (this_instr[1].cache << 1) | flag; #endif @@ -2618,6 +2658,7 @@ dummy_func( replaced op(_POP_JUMP_IF_TRUE, (cond -- )) { assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_Is(cond, PyStackRef_True); + DEAD(cond); #if ENABLE_SPECIALIZATION this_instr[1].cache = (this_instr[1].cache << 1) | flag; #endif @@ -2627,6 +2668,7 @@ dummy_func( op(_IS_NONE, (value -- b)) { if (PyStackRef_Is(value, PyStackRef_None)) { b = PyStackRef_True; + DEAD(value); } else { b = PyStackRef_False; @@ -2699,9 +2741,10 @@ dummy_func( inst(GET_ITER, (iterable -- iter)) { /* before: [obj]; after [getiter(obj)] */ - iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable))); + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); DECREF_INPUTS(); - ERROR_IF(PyStackRef_IsNull(iter), error); + ERROR_IF(iter_o == NULL, error); + iter = PyStackRef_FromPyObjectSteal(iter_o); } inst(GET_YIELD_FROM_ITER, (iterable -- iter)) { @@ -2718,13 +2761,16 @@ dummy_func( ERROR_NO_POP(); } iter = iterable; + DEAD(iterable); } else if (PyGen_CheckExact(iterable_o)) { iter = iterable; + DEAD(iterable); } else { /* `iterable` is not a generator. */ iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o)); + DEAD(iterable); if (PyStackRef_IsNull(iter)) { ERROR_NO_POP(); } @@ -2762,7 +2808,6 @@ dummy_func( PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); if (next_o == NULL) { - next = PyStackRef_NULL; if (_PyErr_Occurred(tstate)) { int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); if (!matches) { @@ -3009,16 +3054,18 @@ dummy_func( PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner); PyObject *name = _Py_SpecialMethods[oparg].name; PyObject *self_or_null_o; - attr = PyStackRef_FromPyObjectSteal(_PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o)); - if (PyStackRef_IsNull(attr)) { + PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o); + if (attr_o == NULL) { if (!_PyErr_Occurred(tstate)) { _PyErr_Format(tstate, PyExc_TypeError, _Py_SpecialMethods[oparg].error, Py_TYPE(owner_o)->tp_name); } + ERROR_IF(true, error); } - ERROR_IF(PyStackRef_IsNull(attr), error); - self_or_null = PyStackRef_FromPyObjectSteal(self_or_null_o); + attr = PyStackRef_FromPyObjectSteal(attr_o); + self_or_null = self_or_null_o == NULL ? + PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o); } inst(WITH_EXCEPT_START, (exit_func, exit_self, lasti, unused, val -- exit_func, exit_self, lasti, unused, val, res)) { @@ -3049,9 +3096,10 @@ dummy_func( (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb}; int has_self = !PyStackRef_IsNull(exit_self); - res = PyStackRef_FromPyObjectSteal(PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, - (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL)); - ERROR_IF(PyStackRef_IsNull(res), error); + PyObject *res_o = PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, + (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + ERROR_IF(res_o == NULL, error); + res = PyStackRef_FromPyObjectSteal(res_o); } pseudo(SETUP_FINALLY, (-- unused), (HAS_ARG)) = { @@ -3078,7 +3126,7 @@ dummy_func( NOP, }; - inst(PUSH_EXC_INFO, (new_exc -- prev_exc, new_exc)) { + inst(PUSH_EXC_INFO, (exc -- prev_exc, new_exc)) { _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { @@ -3087,8 +3135,10 @@ dummy_func( else { prev_exc = PyStackRef_None; } - assert(PyStackRef_ExceptionInstanceCheck(new_exc)); - exc_info->exc_value = PyStackRef_AsPyObjectNew(new_exc); + assert(PyStackRef_ExceptionInstanceCheck(exc)); + exc_info->exc_value = PyStackRef_AsPyObjectNew(exc); + new_exc = exc; + DEAD(exc); } op(_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, (owner -- owner)) { @@ -3111,6 +3161,7 @@ dummy_func( assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); self = owner; + DEAD(owner); } macro(LOAD_ATTR_METHOD_WITH_VALUES) = @@ -3128,6 +3179,7 @@ dummy_func( assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); self = owner; + DEAD(owner); } macro(LOAD_ATTR_METHOD_NO_DICT) = @@ -3180,6 +3232,7 @@ dummy_func( assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); self = owner; + DEAD(owner); } macro(LOAD_ATTR_METHOD_LAZY_DICT) = @@ -3214,11 +3267,11 @@ dummy_func( CALL_NON_PY_GENERAL, }; - specializing op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null[1], args[oparg] -- callable, self_or_null[1], args[oparg])) { + specializing op(_SPECIALIZE_CALL, (counter/1, callable[1], self_or_null[1], args[oparg] -- callable[1], self_or_null[1], args[oparg])) { #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; - _Py_Specialize_Call(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); + _Py_Specialize_Call(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(CALL); @@ -3226,23 +3279,21 @@ dummy_func( #endif /* ENABLE_SPECIALIZATION */ } - op(_MAYBE_EXPAND_METHOD, (callable, self_or_null[1], args[oparg] -- func, maybe_self[1], args[oparg])) { - if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_MAYBE_EXPAND_METHOD, (callable[1], self_or_null[1], args[oparg] -- func[1], maybe_self[1], args[oparg])) { + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *self = ((PyMethodObject *)callable_o)->im_self; maybe_self[0] = PyStackRef_FromPyObjectNew(self); PyObject *method = ((PyMethodObject *)callable_o)->im_func; - func = PyStackRef_FromPyObjectNew(method); - PyStackRef_CLOSE(callable); - } - else { - func = callable; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); } } // When calling Python, inline the call using DISPATCH_INLINED(). - op(_DO_CALL, (callable, self_or_null[1], args[oparg] -- res)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_DO_CALL, (callable[1], self_or_null[1], args[oparg] -- res)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; @@ -3258,11 +3309,11 @@ dummy_func( int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, total_args, NULL, frame ); // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); + SYNC_SP(); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { @@ -3274,10 +3325,11 @@ dummy_func( /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + DEAD(self_or_null); ERROR_IF(true, error); } PyObject *res_o = PyObject_Vectorcall( @@ -3303,17 +3355,18 @@ dummy_func( } } assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + DEAD(self_or_null); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } - op(_MONITOR_CALL, (func, maybe_self[1], args[oparg] -- func, maybe_self[1], args[oparg])) { + op(_MONITOR_CALL, (func[1], maybe_self[1], args[oparg] -- func[1], maybe_self[1], args[oparg])) { int is_meth = !PyStackRef_IsNull(maybe_self[0]); - PyObject *function = PyStackRef_AsPyObjectBorrow(func); + PyObject *function = PyStackRef_AsPyObjectBorrow(func[0]); PyObject *arg0; if (is_meth) { arg0 = PyStackRef_AsPyObjectBorrow(maybe_self[0]); @@ -3324,6 +3377,7 @@ dummy_func( else { arg0 = &_PyInstrumentation_MISSING; } + SYNC_SP(); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, function, arg0 @@ -3334,8 +3388,8 @@ dummy_func( macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + _DO_CALL + _CHECK_PERIODIC; macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + _MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC; - op(_PY_FRAME_GENERAL, (callable, self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_PY_FRAME_GENERAL, (callable[1], self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; @@ -3346,20 +3400,21 @@ dummy_func( assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); - new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + _PyInterpreterFrame *temp = _PyEvalFramePushAndInit( + tstate, callable[0], locals, args, total_args, NULL, frame ); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. + // The frame has stolen all the arguments from the stack. + INPUTS_DEAD(); SYNC_SP(); - if (new_frame == NULL) { + if (temp == NULL) { ERROR_NO_POP(); } + new_frame = temp; } - op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null[1], unused[oparg] -- callable, self_or_null[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_FUNCTION_VERSION, (func_version/2, callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); EXIT_IF(!PyFunction_Check(callable_o)); PyFunctionObject *func = (PyFunctionObject *)callable_o; EXIT_IF(func->func_version != func_version); @@ -3373,8 +3428,8 @@ dummy_func( _SAVE_RETURN_OFFSET + _PUSH_FRAME; - op(_CHECK_METHOD_VERSION, (func_version/2, callable, null[1], unused[oparg] -- callable, null[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_METHOD_VERSION, (func_version/2, callable[1], null[1], unused[oparg] -- callable[1], null[1], unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); EXIT_IF(Py_TYPE(callable_o) != &PyMethod_Type); PyObject *func = ((PyMethodObject *)callable_o)->im_func; @@ -3383,15 +3438,16 @@ dummy_func( EXIT_IF(!PyStackRef_IsNull(null[0])); } - op(_EXPAND_METHOD, (callable, null[1], unused[oparg] -- method, self[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - + op(_EXPAND_METHOD, (callable[1], null[1], unused[oparg] -- method[1], self[1], unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyStackRef_IsNull(null[0])); + DEAD(null); assert(Py_TYPE(callable_o) == &PyMethod_Type); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - assert(PyStackRef_FunctionCheck(method)); - PyStackRef_CLOSE(callable); + _PyStackRef temp = callable[0]; + method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + assert(PyStackRef_FunctionCheck(method[0])); + PyStackRef_CLOSE(temp); } macro(CALL_BOUND_METHOD_GENERAL) = @@ -3404,17 +3460,17 @@ dummy_func( _SAVE_RETURN_OFFSET + _PUSH_FRAME; - op(_CHECK_IS_NOT_PY_CALLABLE, (callable, unused[1], unused[oparg] -- callable, unused[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_IS_NOT_PY_CALLABLE, (callable[1], unused[1], unused[oparg] -- callable[1], unused[1], unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); EXIT_IF(PyFunction_Check(callable_o)); EXIT_IF(Py_TYPE(callable_o) == &PyMethod_Type); } - op(_CALL_NON_PY_GENERAL, (callable, self_or_null[1], args[oparg] -- res)) { + op(_CALL_NON_PY_GENERAL, (callable[1], self_or_null[1], args[oparg] -- res)) { #if TIER_ONE assert(opcode != INSTRUMENTED_CALL); #endif - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3433,10 +3489,11 @@ dummy_func( NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + DEAD(self_or_null); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3448,59 +3505,64 @@ dummy_func( _CALL_NON_PY_GENERAL + _CHECK_PERIODIC; - op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null[1], unused[oparg] -- callable, null[1], unused[oparg])) { + op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], null[1], unused[oparg] -- callable[1], null[1], unused[oparg])) { EXIT_IF(!PyStackRef_IsNull(null[0])); - EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type); + EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable[0])) != &PyMethod_Type); } - op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null[1], unused[oparg] -- func, self[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable[1], null[1], unused[oparg] -- func[1], self[1], unused[oparg])) { + DEAD(null); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); STAT_INC(CALL, hit); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - PyStackRef_CLOSE(callable); + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + PyStackRef_CLOSE(temp); } op(_CHECK_PEP_523, (--)) { DEOPT_IF(tstate->interp->eval_frame); } - op(_CHECK_FUNCTION_EXACT_ARGS, (callable, self_or_null[1], unused[oparg] -- callable, self_or_null[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_FUNCTION_EXACT_ARGS, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyFunction_Check(callable_o)); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; EXIT_IF(code->co_argcount != oparg + (!PyStackRef_IsNull(self_or_null[0]))); } - op(_CHECK_STACK_SPACE, (callable, self_or_null[1], unused[oparg] -- callable, self_or_null[1], unused[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_STACK_SPACE, (callable[1], self_or_null[1], unused[oparg] -- callable[1], self_or_null[1], unused[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); DEOPT_IF(tstate->py_recursion_remaining <= 1); } - replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) { + replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable[1], self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) { int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { first_non_self_local[i] = args[i]; } + INPUTS_DEAD(); } op(_PUSH_FRAME, (new_frame: _PyInterpreterFrame* -- )) { // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; + DEAD(new_frame); SYNC_SP(); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -3536,7 +3598,9 @@ dummy_func( assert(oparg == 1); DEOPT_IF(!PyStackRef_IsNull(null)); + DEAD(null); DEOPT_IF(callable_o != (PyObject *)&PyType_Type); + DEAD(callable); STAT_INC(CALL, hit); res = PyStackRef_FromPyObjectSteal(Py_NewRef(Py_TYPE(arg_o))); PyStackRef_CLOSE(arg); @@ -3551,6 +3615,8 @@ dummy_func( DEOPT_IF(callable_o != (PyObject *)&PyUnicode_Type); STAT_INC(CALL, hit); res = PyStackRef_FromPyObjectSteal(PyObject_Str(arg_o)); + DEAD(null); + DEAD(callable); PyStackRef_CLOSE(arg); ERROR_IF(PyStackRef_IsNull(res), error); } @@ -3570,6 +3636,8 @@ dummy_func( DEOPT_IF(callable_o != (PyObject *)&PyTuple_Type); STAT_INC(CALL, hit); res = PyStackRef_FromPyObjectSteal(PySequence_Tuple(arg_o)); + DEAD(null); + DEAD(callable); PyStackRef_CLOSE(arg); ERROR_IF(PyStackRef_IsNull(res), error); } @@ -3580,9 +3648,9 @@ dummy_func( _CALL_TUPLE_1 + _CHECK_PERIODIC; - op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, null, args[oparg] -- self, init, args[oparg])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyStackRef_IsNull(null)); + op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable[1], null[1], args[oparg] -- init[1], self[1], args[oparg])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); + DEOPT_IF(!PyStackRef_IsNull(null[0])); DEOPT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; DEOPT_IF(tp->tp_version_tag != type_version); @@ -3592,23 +3660,26 @@ dummy_func( PyCodeObject *code = (PyCodeObject *)init_func->func_code; DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize)); STAT_INC(CALL, hit); - self = PyStackRef_FromPyObjectSteal(_PyType_NewManagedObject(tp)); - if (PyStackRef_IsNull(self)) { + PyObject *self_o = _PyType_NewManagedObject(tp); + if (self_o == NULL) { ERROR_NO_POP(); } - PyStackRef_CLOSE(callable); - init = PyStackRef_FromPyObjectNew(init_func); + self[0] = PyStackRef_FromPyObjectSteal(self_o); + _PyStackRef temp = callable[0]; + init[0] = PyStackRef_FromPyObjectNew(init_func); + PyStackRef_CLOSE(temp); } - op(_CREATE_INIT_FRAME, (self, init, args[oparg] -- init_frame: _PyInterpreterFrame *)) { + op(_CREATE_INIT_FRAME, (init[1], self[1], args[oparg] -- init_frame: _PyInterpreterFrame *)) { _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( tstate, (PyCodeObject *)&_Py_InitCleanup, 1, frame); assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK); /* Push self onto stack of shim */ - shim->localsplus[0] = PyStackRef_DUP(self); - args[-1] = self; + shim->localsplus[0] = PyStackRef_DUP(self[0]); + DEAD(init); + DEAD(self); init_frame = _PyEvalFramePushAndInit( - tstate, init, NULL, args-1, oparg+1, NULL, shim); + tstate, init[0], NULL, args-1, oparg+1, NULL, shim); SYNC_SP(); if (init_frame == NULL) { _PyEval_FrameClearAndPop(tstate, shim); @@ -3636,16 +3707,18 @@ dummy_func( Py_TYPE(PyStackRef_AsPyObjectBorrow(should_be_none))->tp_name); ERROR_NO_POP(); } + DEAD(should_be_none); } - op(_CALL_BUILTIN_CLASS, (callable, self_or_null[1], args[oparg] -- res)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CALL_BUILTIN_CLASS, (callable[1], self_or_null[1], args[oparg] -- res)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; total_args++; } + DEAD(self_or_null); DEOPT_IF(!PyType_Check(callable_o)); PyTypeObject *tp = (PyTypeObject *)callable_o; DEOPT_IF(tp->tp_vectorcall == NULL); @@ -3661,7 +3734,7 @@ dummy_func( for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3672,9 +3745,9 @@ dummy_func( _CALL_BUILTIN_CLASS + _CHECK_PERIODIC; - op(_CALL_BUILTIN_O, (callable, self_or_null[1], args[oparg] -- res)) { + op(_CALL_BUILTIN_O, (callable[1], self_or_null[1], args[oparg] -- res)) { /* Builtin METH_O functions */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3695,7 +3768,9 @@ dummy_func( assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(arg); - PyStackRef_CLOSE(callable); + DEAD(args); + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3706,15 +3781,16 @@ dummy_func( _CALL_BUILTIN_O + _CHECK_PERIODIC; - op(_CALL_BUILTIN_FAST, (callable, self_or_null[1], args[oparg] -- res)) { + op(_CALL_BUILTIN_FAST, (callable[1], self_or_null[1], args[oparg] -- res)) { /* Builtin METH_FASTCALL functions, without keywords */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; total_args++; } + DEAD(self_or_null); DEOPT_IF(!PyCFunction_CheckExact(callable_o)); DEOPT_IF(PyCFunction_GET_FLAGS(callable_o) != METH_FASTCALL); STAT_INC(CALL, hit); @@ -3736,7 +3812,7 @@ dummy_func( for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3747,9 +3823,9 @@ dummy_func( _CALL_BUILTIN_FAST + _CHECK_PERIODIC; - op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null[1], args[oparg] -- res)) { + op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable[1], self_or_null[1], args[oparg] -- res)) { /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3778,7 +3854,8 @@ dummy_func( for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3789,9 +3866,9 @@ dummy_func( _CALL_BUILTIN_FAST_WITH_KEYWORDS + _CHECK_PERIODIC; - inst(CALL_LEN, (unused/1, unused/2, callable, self_or_null[1], args[oparg] -- res)) { + inst(CALL_LEN, (unused/1, unused/2, callable[1], self_or_null[1], args[oparg] -- res)) { /* len(o) */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3813,14 +3890,14 @@ dummy_func( if (res_o == NULL) { GOTO_ERROR(error); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(arg_stackref); res = PyStackRef_FromPyObjectSteal(res_o); } - inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null[1], args[oparg] -- res)) { + inst(CALL_ISINSTANCE, (unused/1, unused/2, callable[1], self_or_null[1], args[oparg] -- res)) { /* isinstance(o, o2) */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3841,7 +3918,7 @@ dummy_func( assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(inst_stackref); PyStackRef_CLOSE(cls_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); } // This is secretly a super-instruction @@ -3867,8 +3944,8 @@ dummy_func( #endif } - op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null[1], args[oparg] -- res)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CALL_METHOD_DESCRIPTOR_O, (callable[1], self_or_null[1], args[oparg] -- res)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3897,7 +3974,9 @@ dummy_func( assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(self_stackref); PyStackRef_CLOSE(arg_stackref); - PyStackRef_CLOSE(callable); + DEAD(args); + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3908,8 +3987,8 @@ dummy_func( _CALL_METHOD_DESCRIPTOR_O + _CHECK_PERIODIC; - op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable, self_or_null[1], args[oparg] -- res)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (callable[1], self_or_null[1], args[oparg] -- res)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3925,14 +4004,14 @@ dummy_func( EXIT_IF(!Py_IS_TYPE(self, d_type)); STAT_INC(CALL, hit); int nargs = total_args - 1; - PyCFunctionFastWithKeywords cfunc = - (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); ERROR_IF(true, error); } + PyCFunctionFastWithKeywords cfunc = + (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; PyObject *res_o = cfunc(self, (args_o + 1), nargs, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -3941,7 +4020,8 @@ dummy_func( for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3952,9 +4032,9 @@ dummy_func( _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS + _CHECK_PERIODIC; - op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable, self_or_null[1], args[oparg] -- res)) { + op(_CALL_METHOD_DESCRIPTOR_NOARGS, (callable[1], self_or_null[1], args[oparg] -- res)) { assert(oparg == 0 || oparg == 1); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3978,7 +4058,9 @@ dummy_func( _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(self_stackref); - PyStackRef_CLOSE(callable); + DEAD(args); + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3989,8 +4071,8 @@ dummy_func( _CALL_METHOD_DESCRIPTOR_NOARGS + _CHECK_PERIODIC; - op(_CALL_METHOD_DESCRIPTOR_FAST, (callable, self_or_null[1], args[oparg] -- res)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CALL_METHOD_DESCRIPTOR_FAST, (callable[1], self_or_null[1], args[oparg] -- res)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -4005,8 +4087,6 @@ dummy_func( PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); EXIT_IF(!Py_IS_TYPE(self, method->d_common.d_type)); STAT_INC(CALL, hit); - PyCFunctionFast cfunc = - (PyCFunctionFast)(void(*)(void))meth->ml_meth; int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(args, total_args, args_o); @@ -4014,6 +4094,8 @@ dummy_func( DECREF_INPUTS(); ERROR_IF(true, error); } + PyCFunctionFast cfunc = + (PyCFunctionFast)(void(*)(void))meth->ml_meth; PyObject *res_o = cfunc(self, (args_o + 1), nargs); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -4022,7 +4104,8 @@ dummy_func( for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4054,8 +4137,22 @@ dummy_func( GO_TO_INSTRUCTION(CALL_KW); } - op(_DO_CALL_KW, (callable, self_or_null[1], args[oparg], kwnames -- res)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_MAYBE_EXPAND_METHOD_KW, (callable[1], self_or_null[1], args[oparg], kwnames_in -- func[1], maybe_self[1], args[oparg], kwnames_out)) { + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); + PyObject *self = ((PyMethodObject *)callable_o)->im_self; + maybe_self[0] = PyStackRef_FromPyObjectNew(self); + PyObject *method = ((PyMethodObject *)callable_o)->im_func; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); + } + kwnames_out = kwnames_in; + DEAD(kwnames_in); + } + + op(_DO_CALL_KW, (callable[1], self_or_null[1], args[oparg], kwnames -- res)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); // oparg counts all of the args, but *not* self: @@ -4064,17 +4161,6 @@ dummy_func( args--; total_args++; } - else if (Py_TYPE(callable_o) == &PyMethod_Type) { - args--; - total_args++; - PyObject *self = ((PyMethodObject *)callable_o)->im_self; - args[0] = PyStackRef_FromPyObjectNew(self); - PyObject *method = ((PyMethodObject *)callable_o)->im_func; - args[-1] = PyStackRef_FromPyObjectNew(method); - PyStackRef_CLOSE(callable); - callable_o = method; - callable = args[-1]; - } int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); // Check if the call can be inlined or not if (Py_TYPE(callable_o) == &PyFunction_Type && @@ -4084,12 +4170,12 @@ dummy_func( int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, positional_args, kwnames_o, frame ); PyStackRef_CLOSE(kwnames); - // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 3); + // Sync stack explicitly since we leave using DISPATCH_INLINED(). + SYNC_SP(); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { @@ -4129,16 +4215,17 @@ dummy_func( } PyStackRef_CLOSE(kwnames); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + DEAD(self_or_null); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } - op(_PY_FRAME_KW, (callable, self_or_null[1], args[oparg], kwnames -- new_frame: _PyInterpreterFrame*)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_PY_FRAME_KW, (callable[1], self_or_null[1], args[oparg], kwnames -- new_frame: _PyInterpreterFrame*)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; @@ -4152,7 +4239,7 @@ dummy_func( int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, positional_args, kwnames_o, frame ); PyStackRef_CLOSE(kwnames); @@ -4164,8 +4251,8 @@ dummy_func( } } - op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable, self_or_null[1], unused[oparg], kwnames -- callable, self_or_null[1], unused[oparg], kwnames)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable[1], self_or_null[1], unused[oparg], kwnames -- callable[1], self_or_null[1], unused[oparg], kwnames)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); EXIT_IF(!PyFunction_Check(callable_o)); PyFunctionObject *func = (PyFunctionObject *)callable_o; EXIT_IF(func->func_version != func_version); @@ -4179,8 +4266,8 @@ dummy_func( _SAVE_RETURN_OFFSET + _PUSH_FRAME; - op(_CHECK_METHOD_VERSION_KW, (func_version/2, callable, null[1], unused[oparg], kwnames -- callable, null[1], unused[oparg], kwnames)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_METHOD_VERSION_KW, (func_version/2, callable[1], null[1], unused[oparg], kwnames -- callable[1], null[1], unused[oparg], kwnames)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); EXIT_IF(Py_TYPE(callable_o) != &PyMethod_Type); PyObject *func = ((PyMethodObject *)callable_o)->im_func; @@ -4189,15 +4276,16 @@ dummy_func( EXIT_IF(!PyStackRef_IsNull(null[0])); } - op(_EXPAND_METHOD_KW, (callable, null[1], unused[oparg], kwnames -- method, self[1], unused[oparg], kwnames)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_EXPAND_METHOD_KW, (callable[1], null[1], unused[oparg], unused -- method[1], self[1], unused[oparg], unused)) { + _PyStackRef callable_s = callable[0]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable_s); assert(PyStackRef_IsNull(null[0])); assert(Py_TYPE(callable_o) == &PyMethod_Type); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - assert(PyStackRef_FunctionCheck(method)); - PyStackRef_CLOSE(callable); + method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + assert(PyStackRef_FunctionCheck(method[0])); + PyStackRef_CLOSE(callable_s); } macro(CALL_KW_BOUND_METHOD) = @@ -4210,11 +4298,11 @@ dummy_func( _SAVE_RETURN_OFFSET + _PUSH_FRAME; - specializing op(_SPECIALIZE_CALL_KW, (counter/1, callable, self_or_null[1], args[oparg], kwnames -- callable, self_or_null[1], args[oparg], kwnames)) { + specializing op(_SPECIALIZE_CALL_KW, (counter/1, callable[1], self_or_null[1], args[oparg], kwnames -- callable[1], self_or_null[1], args[oparg], kwnames)) { #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; - _Py_Specialize_CallKw(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); + _Py_Specialize_CallKw(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(CALL_KW); @@ -4225,20 +4313,21 @@ dummy_func( macro(CALL_KW) = _SPECIALIZE_CALL_KW + unused/2 + + _MAYBE_EXPAND_METHOD_KW + _DO_CALL_KW; - op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable, unused[1], unused[oparg], kwnames -- callable, unused[1], unused[oparg], kwnames)) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable[1], unused[1], unused[oparg], kwnames -- callable[1], unused[1], unused[oparg], kwnames)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); EXIT_IF(PyFunction_Check(callable_o)); EXIT_IF(Py_TYPE(callable_o) == &PyMethod_Type); } - op(_CALL_KW_NON_PY, (callable, self_or_null[1], args[oparg], kwnames -- res)) { + op(_CALL_KW_NON_PY, (callable[1], self_or_null[1], args[oparg], kwnames -- res)) { #if TIER_ONE assert(opcode != INSTRUMENTED_CALL); #endif - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -4260,10 +4349,11 @@ dummy_func( PyStackRef_CLOSE(kwnames); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + DEAD(self_or_null); + PyStackRef_CLOSE(callable[0]); ERROR_IF(res_o == NULL, error); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4279,7 +4369,29 @@ dummy_func( GO_TO_INSTRUCTION(CALL_FUNCTION_EX); } - inst(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) { + op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in if (oparg & 1) -- func, unused, tuple, kwargs_out if (oparg & 1))) { + PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs); + if (PyTuple_CheckExact(callargs_o)) { + tuple = callargs; + DEAD(callargs); + } + else { + int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o); + if (err < 0) { + ERROR_NO_POP(); + } + PyObject *tuple_o = PySequence_Tuple(callargs_o); + if (tuple_o == NULL) { + ERROR_NO_POP(); + } + PyStackRef_CLOSE(callargs); + tuple = PyStackRef_FromPyObjectSteal(tuple_o); + } + kwargs_out = kwargs_in; + DEAD(kwargs_in); + } + + op(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) { PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st); PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st); @@ -4287,32 +4399,23 @@ dummy_func( // DICT_MERGE is called before this opcode if there are kwargs. // It converts all dict subtypes in kwargs into regular dicts. assert(kwargs == NULL || PyDict_CheckExact(kwargs)); - if (!PyTuple_CheckExact(callargs)) { - int err = check_args_iterable(tstate, func, callargs); - if (err < 0) { - ERROR_NO_POP(); - } - PyObject *tuple = PySequence_Tuple(callargs); - if (tuple == NULL) { - ERROR_NO_POP(); - } - PyStackRef_CLOSE(callargs_st); - callargs_st = PyStackRef_FromPyObjectSteal(tuple); - callargs = tuple; - } assert(PyTuple_CheckExact(callargs)); EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); + PyObject *result_o; + assert(!_PyErr_Occurred(tstate)); if (opcode == INSTRUMENTED_CALL_FUNCTION_EX) { PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ? PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING; int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, func, arg); - if (err) ERROR_NO_POP(); - result = PyStackRef_FromPyObjectSteal(PyObject_Call(func, callargs, kwargs)); + if (err) { + ERROR_NO_POP(); + } + result_o = PyObject_Call(func, callargs, kwargs); if (!PyFunction_Check(func) && !PyMethod_Check(func)) { - if (PyStackRef_IsNull(result)) { + if (result_o == NULL) { _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, frame, this_instr, func, arg); @@ -4322,7 +4425,7 @@ dummy_func( tstate, PY_MONITORING_EVENT_C_RETURN, frame, this_instr, func, arg); if (err < 0) { - PyStackRef_CLEAR(result); + Py_CLEAR(result_o); } } } @@ -4339,8 +4442,9 @@ dummy_func( _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex( tstate, func_st, locals, nargs, callargs, kwargs, frame); - // Need to manually shrink the stack since we exit with DISPATCH_INLINED. - STACK_SHRINK(oparg + 3); + // Need to sync the stack since we exit with DISPATCH_INLINED. + INPUTS_DEAD(); + SYNC_SP(); if (new_frame == NULL) { ERROR_NO_POP(); } @@ -4348,14 +4452,18 @@ dummy_func( frame->return_offset = 1; DISPATCH_INLINED(new_frame); } - result = PyStackRef_FromPyObjectSteal(PyObject_Call(func, callargs, kwargs)); + result_o = PyObject_Call(func, callargs, kwargs); } - DECREF_INPUTS(); - assert(PyStackRef_AsPyObjectBorrow(PEEK(2 + (oparg & 1))) == NULL); - ERROR_IF(PyStackRef_IsNull(result), error); + PyStackRef_XCLOSE(kwargs_st); + DEAD(kwargs_st); + PyStackRef_CLOSE(callargs_st); + PyStackRef_CLOSE(func_st); + ERROR_IF(result_o == NULL, error); + result = PyStackRef_FromPyObjectSteal(result_o); } macro(CALL_FUNCTION_EX) = + _MAKE_CALLARGS_A_TUPLE + _DO_CALL_FUNCTION_EX + _CHECK_PERIODIC; @@ -4367,59 +4475,33 @@ dummy_func( PyFunction_New(codeobj, GLOBALS()); PyStackRef_CLOSE(codeobj_st); - if (func_obj == NULL) { - ERROR_NO_POP(); - } + ERROR_IF(func_obj == NULL, error); _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); } - inst(SET_FUNCTION_ATTRIBUTE, (attr_st, func_st -- func_st)) { - PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - PyObject *attr = PyStackRef_AsPyObjectBorrow(attr_st); - + inst(SET_FUNCTION_ATTRIBUTE, (attr_st, func_in -- func_out)) { + PyObject *func = PyStackRef_AsPyObjectBorrow(func_in); + PyObject *attr = PyStackRef_AsPyObjectSteal(attr_st); + func_out = func_in; + DEAD(func_in); assert(PyFunction_Check(func)); - PyFunctionObject *func_obj = (PyFunctionObject *)func; - switch(oparg) { - case MAKE_FUNCTION_CLOSURE: - assert(func_obj->func_closure == NULL); - func_obj->func_closure = attr; - break; - case MAKE_FUNCTION_ANNOTATIONS: - assert(func_obj->func_annotations == NULL); - func_obj->func_annotations = attr; - break; - case MAKE_FUNCTION_KWDEFAULTS: - assert(PyDict_CheckExact(attr)); - assert(func_obj->func_kwdefaults == NULL); - func_obj->func_kwdefaults = attr; - break; - case MAKE_FUNCTION_DEFAULTS: - assert(PyTuple_CheckExact(attr)); - assert(func_obj->func_defaults == NULL); - func_obj->func_defaults = attr; - break; - case MAKE_FUNCTION_ANNOTATE: - assert(PyCallable_Check(attr)); - assert(func_obj->func_annotate == NULL); - func_obj->func_annotate = attr; - break; - default: - Py_UNREACHABLE(); - } + size_t offset = _Py_FunctionAttributeOffsets[oparg]; + assert(offset != 0); + PyObject **ptr = (PyObject **)(((char *)func) + offset); + assert(*ptr == NULL); + *ptr = attr; } inst(RETURN_GENERATOR, (-- res)) { assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - if (gen == NULL) { - ERROR_NO_POP(); - } + ERROR_IF(gen == NULL, error); assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); + SAVE_STACK(); _PyInterpreterFrame *gen_frame = &gen->gi_iframe; frame->instr_ptr++; _PyFrame_Copy(frame, gen_frame); @@ -4427,12 +4509,12 @@ dummy_func( gen->gi_frame_state = FRAME_CREATED; gen_frame->owner = FRAME_OWNED_BY_GENERATOR; _Py_LeaveRecursiveCallPy(tstate); - res = PyStackRef_FromPyObjectSteal((PyObject *)gen); _PyInterpreterFrame *prev = frame->previous; _PyThreadState_PopFrame(tstate, frame); frame = tstate->current_frame = prev; LOAD_IP(frame->return_offset); - LOAD_SP(); + RELOAD_STACK(); + res = PyStackRef_FromPyObjectSteal((PyObject *)gen); LLTRACE_RESUME_FRAME(); } @@ -4462,12 +4544,14 @@ dummy_func( /* If value is a unicode object, then we know the result * of format(value) is value itself. */ if (!PyUnicode_CheckExact(value_o)) { - res = PyStackRef_FromPyObjectSteal(PyObject_Format(value_o, NULL)); + PyObject *res_o = PyObject_Format(value_o, NULL); PyStackRef_CLOSE(value); - ERROR_IF(PyStackRef_IsNull(res), error); + ERROR_IF(res_o == NULL, error); + res = PyStackRef_FromPyObjectSteal(res_o); } else { res = value; + DEAD(value); } } @@ -4511,8 +4595,12 @@ dummy_func( macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _BINARY_OP; - pure inst(SWAP, (bottom, unused[oparg-2], top -- - top, unused[oparg-2], bottom)) { + pure inst(SWAP, (bottom_in, unused[oparg-2], top_in -- + top_out, unused[oparg-2], bottom_out)) { + bottom_out = bottom_in; + DEAD(bottom_in); + top_out = top_in; + DEAD(top_in); assert(oparg >= 2); } @@ -4523,10 +4611,8 @@ dummy_func( original_opcode = code->_co_monitoring->lines[(int)(this_instr - _PyCode_CODE(code))].original_opcode; next_instr = this_instr; } else { - _PyFrame_SetStackPointer(frame, stack_pointer); original_opcode = _Py_call_instrumentation_line( tstate, frame, this_instr, prev_instr); - stack_pointer = _PyFrame_GetStackPointer(frame); if (original_opcode < 0) { next_instr = this_instr+1; goto error; @@ -4649,29 +4735,34 @@ dummy_func( ///////// Tier-2 only opcodes ///////// op (_GUARD_IS_TRUE_POP, (flag -- )) { + int is_true = PyStackRef_Is(flag, PyStackRef_True); + DEAD(flag); SYNC_SP(); - EXIT_IF(!PyStackRef_Is(flag, PyStackRef_True)); - assert(PyStackRef_Is(flag, PyStackRef_True)); + EXIT_IF(!is_true); } op (_GUARD_IS_FALSE_POP, (flag -- )) { + int is_false = PyStackRef_Is(flag, PyStackRef_False); + DEAD(flag); SYNC_SP(); - EXIT_IF(!PyStackRef_Is(flag, PyStackRef_False)); - assert(PyStackRef_Is(flag, PyStackRef_False)); + EXIT_IF(!is_false); } op (_GUARD_IS_NONE_POP, (val -- )) { - SYNC_SP(); - if (!PyStackRef_Is(val, PyStackRef_None)) { + int is_none = PyStackRef_Is(val, PyStackRef_None); + if (!is_none) { PyStackRef_CLOSE(val); + SYNC_SP(); EXIT_IF(1); } + DEAD(val); } op (_GUARD_IS_NOT_NONE_POP, (val -- )) { - SYNC_SP(); - EXIT_IF(PyStackRef_Is(val, PyStackRef_None)); + int is_none = PyStackRef_Is(val, PyStackRef_None); PyStackRef_CLOSE(val); + SYNC_SP(); + EXIT_IF(is_none); } op(_JUMP_TO_TOP, (--)) { @@ -4707,7 +4798,7 @@ dummy_func( printf("SIDE EXIT: [UOp "); _PyUOpPrint(&next_uop[-1]); printf(", exit %u, temp %d, target %d -> %s]\n", - exit - current_executor->exits, exit->temperature.as_counter, + exit - current_executor->exits, exit->temperature.value_and_backoff, (int)(target - _PyCode_CODE(code)), _PyOpcode_OpName[target->op.code]); } @@ -4784,6 +4875,7 @@ dummy_func( op(_INTERNAL_INCREMENT_OPT_COUNTER, (opt --)) { _PyCounterOptimizerObject *exe = (_PyCounterOptimizerObject *)PyStackRef_AsPyObjectBorrow(opt); exe->count++; + DEAD(opt); } tier2 op(_DYNAMIC_EXIT, (exit_p/4 --)) { @@ -4796,7 +4888,7 @@ dummy_func( printf("DYNAMIC EXIT: [UOp "); _PyUOpPrint(&next_uop[-1]); printf(", exit %u, temp %d, target %d -> %s]\n", - exit - current_executor->exits, exit->temperature.as_counter, + exit - current_executor->exits, exit->temperature.value_and_backoff, (int)(target - _PyCode_CODE(_PyFrame_GetCode(frame))), _PyOpcode_OpName[target->op.code]); } diff --git a/Python/ceval.c b/Python/ceval.c index 6e62939adb3745..ba5c70b25f0a89 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -274,7 +274,6 @@ static void monitor_throw(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); -static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg); static int get_exception_handler(PyCodeObject *, int, int*, int*, int*); static _PyInterpreterFrame * _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, _PyStackRef func, @@ -394,6 +393,13 @@ const _Py_SpecialMethod _Py_SpecialMethods[] = { } }; +const size_t _Py_FunctionAttributeOffsets[] = { + [MAKE_FUNCTION_CLOSURE] = offsetof(PyFunctionObject, func_closure), + [MAKE_FUNCTION_ANNOTATIONS] = offsetof(PyFunctionObject, func_annotations), + [MAKE_FUNCTION_KWDEFAULTS] = offsetof(PyFunctionObject, func_kwdefaults), + [MAKE_FUNCTION_DEFAULTS] = offsetof(PyFunctionObject, func_defaults), + [MAKE_FUNCTION_ANNOTATE] = offsetof(PyFunctionObject, func_annotate), +}; // PEP 634: Structural Pattern Matching @@ -1036,6 +1042,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int uopcode = next_uop->opcode; #ifdef Py_DEBUG if (lltrace >= 3) { + dump_stack(frame, stack_pointer); if (next_uop->opcode == _START_EXECUTOR) { printf("%4d uop: ", 0); } @@ -1043,8 +1050,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int printf("%4d uop: ", (int)(next_uop - current_executor->trace)); } _PyUOpPrint(next_uop); - printf(" stack_level=%d\n", - (int)(stack_pointer - _PyFrame_Stackbase(frame))); + printf("\n"); } #endif next_uop++; @@ -2920,11 +2926,11 @@ _PyEval_CheckExceptStarTypeValid(PyThreadState *tstate, PyObject* right) return 0; } -static int -check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args) +int +_Py_Check_ArgsIterable(PyThreadState *tstate, PyObject *func, PyObject *args) { if (Py_TYPE(args)->tp_iter == NULL && !PySequence_Check(args)) { - /* check_args_iterable() may be called with a live exception: + /* _Py_Check_ArgsIterable() may be called with a live exception: * clear it to prevent calling _PyObject_FunctionStr() with an * exception set. */ _PyErr_Clear(tstate); diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c index 1d9381d09dfb62..4c9f59f837e11b 100644 --- a/Python/ceval_gil.c +++ b/Python/ceval_gil.c @@ -7,6 +7,7 @@ #include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystats.h" // _Py_PrintSpecializationStats() +#include "pycore_pythread.h" // PyThread_hang_thread() /* Notes about the implementation: @@ -277,10 +278,9 @@ drop_gil(PyInterpreterState *interp, PyThreadState *tstate, int final_release) /* Take the GIL. The function saves errno at entry and restores its value at exit. + It may hang rather than return if the interpreter has been finalized. - tstate must be non-NULL. - - Returns 1 if the GIL was acquired, or 0 if not. */ + tstate must be non-NULL. */ static void take_gil(PyThreadState *tstate) { @@ -293,12 +293,18 @@ take_gil(PyThreadState *tstate) if (_PyThreadState_MustExit(tstate)) { /* bpo-39877: If Py_Finalize() has been called and tstate is not the - thread which called Py_Finalize(), exit immediately the thread. + thread which called Py_Finalize(), this thread cannot continue. This code path can be reached by a daemon thread after Py_Finalize() completes. In this case, tstate is a dangling pointer: points to - PyThreadState freed memory. */ - PyThread_exit_thread(); + PyThreadState freed memory. + + This used to call a *thread_exit API, but that was not safe as it + lacks stack unwinding and local variable destruction important to + C++. gh-87135: The best that can be done is to hang the thread as + the public APIs calling this have no error reporting mechanism (!). + */ + PyThread_hang_thread(); } assert(_PyThreadState_CheckConsistency(tstate)); @@ -342,7 +348,9 @@ take_gil(PyThreadState *tstate) if (drop_requested) { _Py_unset_eval_breaker_bit(holder_tstate, _PY_GIL_DROP_REQUEST_BIT); } - PyThread_exit_thread(); + // gh-87135: hang the thread as *thread_exit() is not a safe + // API. It lacks stack unwind and local variable destruction. + PyThread_hang_thread(); } assert(_PyThreadState_CheckConsistency(tstate)); @@ -383,7 +391,7 @@ take_gil(PyThreadState *tstate) if (_PyThreadState_MustExit(tstate)) { /* bpo-36475: If Py_Finalize() has been called and tstate is not - the thread which called Py_Finalize(), exit immediately the + the thread which called Py_Finalize(), gh-87135: hang the thread. This code path can be reached by a daemon thread which was waiting @@ -393,7 +401,7 @@ take_gil(PyThreadState *tstate) /* tstate could be a dangling pointer, so don't pass it to drop_gil(). */ drop_gil(interp, NULL, 1); - PyThread_exit_thread(); + PyThread_hang_thread(); } assert(_PyThreadState_CheckConsistency(tstate)); diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h index 9e1540674d4219..e0e9cc156ed62f 100644 --- a/Python/ceval_macros.h +++ b/Python/ceval_macros.h @@ -108,6 +108,7 @@ do { \ /* Do interpreter dispatch accounting for tracing and instrumentation */ #define DISPATCH() \ { \ + assert(frame->stackpointer == NULL); \ NEXTOPARG(); \ PRE_DISPATCH_GOTO(); \ DISPATCH_GOTO(); \ diff --git a/Python/clinic/instrumentation.c.h b/Python/clinic/instrumentation.c.h index 8dae747c44a543..9b3373bc1a67a5 100644 --- a/Python/clinic/instrumentation.c.h +++ b/Python/clinic/instrumentation.c.h @@ -36,6 +36,33 @@ monitoring_use_tool_id(PyObject *module, PyObject *const *args, Py_ssize_t nargs return return_value; } +PyDoc_STRVAR(monitoring_clear_tool_id__doc__, +"clear_tool_id($module, tool_id, /)\n" +"--\n" +"\n"); + +#define MONITORING_CLEAR_TOOL_ID_METHODDEF \ + {"clear_tool_id", (PyCFunction)monitoring_clear_tool_id, METH_O, monitoring_clear_tool_id__doc__}, + +static PyObject * +monitoring_clear_tool_id_impl(PyObject *module, int tool_id); + +static PyObject * +monitoring_clear_tool_id(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int tool_id; + + tool_id = PyLong_AsInt(arg); + if (tool_id == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = monitoring_clear_tool_id_impl(module, tool_id); + +exit: + return return_value; +} + PyDoc_STRVAR(monitoring_free_tool_id__doc__, "free_tool_id($module, tool_id, /)\n" "--\n" @@ -304,4 +331,4 @@ monitoring__all_events(PyObject *module, PyObject *Py_UNUSED(ignored)) { return monitoring__all_events_impl(module); } -/*[clinic end generated code: output=14ffc0884a6de50a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8f81876c6aba9be8 input=a9049054013a1b77]*/ diff --git a/Python/codegen.c b/Python/codegen.c index 896c30cc14952a..689d2b5124e9d3 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -194,6 +194,7 @@ static int codegen_visit_expr(compiler *, expr_ty); static int codegen_augassign(compiler *, stmt_ty); static int codegen_annassign(compiler *, stmt_ty); static int codegen_subscript(compiler *, expr_ty); +static int codegen_slice_two_parts(compiler *, expr_ty); static int codegen_slice(compiler *, expr_ty); static bool are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t); @@ -5005,12 +5006,8 @@ codegen_visit_expr(compiler *c, expr_ty e) } break; case Slice_kind: - { - int n = codegen_slice(c, e); - RETURN_IF_ERROR(n); - ADDOP_I(c, loc, BUILD_SLICE, n); + RETURN_IF_ERROR(codegen_slice(c, e)); break; - } case Name_kind: return codegen_nameop(c, loc, e->v.Name.id, e->v.Name.ctx); /* child nodes of List and Tuple will have expr_context set */ @@ -5023,9 +5020,22 @@ codegen_visit_expr(compiler *c, expr_ty e) } static bool -is_two_element_slice(expr_ty s) +is_constant_slice(expr_ty s) { return s->kind == Slice_kind && + (s->v.Slice.lower == NULL || + s->v.Slice.lower->kind == Constant_kind) && + (s->v.Slice.upper == NULL || + s->v.Slice.upper->kind == Constant_kind) && + (s->v.Slice.step == NULL || + s->v.Slice.step->kind == Constant_kind); +} + +static bool +should_apply_two_element_slice_optimization(expr_ty s) +{ + return !is_constant_slice(s) && + s->kind == Slice_kind && s->v.Slice.step == NULL; } @@ -5046,8 +5056,8 @@ codegen_augassign(compiler *c, stmt_ty s) break; case Subscript_kind: VISIT(c, expr, e->v.Subscript.value); - if (is_two_element_slice(e->v.Subscript.slice)) { - RETURN_IF_ERROR(codegen_slice(c, e->v.Subscript.slice)); + if (should_apply_two_element_slice_optimization(e->v.Subscript.slice)) { + RETURN_IF_ERROR(codegen_slice_two_parts(c, e->v.Subscript.slice)); ADDOP_I(c, loc, COPY, 3); ADDOP_I(c, loc, COPY, 3); ADDOP_I(c, loc, COPY, 3); @@ -5084,7 +5094,7 @@ codegen_augassign(compiler *c, stmt_ty s) ADDOP_NAME(c, loc, STORE_ATTR, e->v.Attribute.attr, names); break; case Subscript_kind: - if (is_two_element_slice(e->v.Subscript.slice)) { + if (should_apply_two_element_slice_optimization(e->v.Subscript.slice)) { ADDOP_I(c, loc, SWAP, 4); ADDOP_I(c, loc, SWAP, 3); ADDOP_I(c, loc, SWAP, 2); @@ -5231,8 +5241,10 @@ codegen_subscript(compiler *c, expr_ty e) } VISIT(c, expr, e->v.Subscript.value); - if (is_two_element_slice(e->v.Subscript.slice) && ctx != Del) { - RETURN_IF_ERROR(codegen_slice(c, e->v.Subscript.slice)); + if (should_apply_two_element_slice_optimization(e->v.Subscript.slice) && + ctx != Del + ) { + RETURN_IF_ERROR(codegen_slice_two_parts(c, e->v.Subscript.slice)); if (ctx == Load) { ADDOP(c, loc, BINARY_SLICE); } @@ -5254,15 +5266,9 @@ codegen_subscript(compiler *c, expr_ty e) return SUCCESS; } -/* Returns the number of the values emitted, - * thus are needed to build the slice, or -1 if there is an error. */ static int -codegen_slice(compiler *c, expr_ty s) +codegen_slice_two_parts(compiler *c, expr_ty s) { - int n = 2; - assert(s->kind == Slice_kind); - - /* only handles the cases where BUILD_SLICE is emitted */ if (s->v.Slice.lower) { VISIT(c, expr, s->v.Slice.lower); } @@ -5277,11 +5283,45 @@ codegen_slice(compiler *c, expr_ty s) ADDOP_LOAD_CONST(c, LOC(s), Py_None); } + return 0; +} + +static int +codegen_slice(compiler *c, expr_ty s) +{ + int n = 2; + assert(s->kind == Slice_kind); + + if (is_constant_slice(s)) { + PyObject *start = NULL; + if (s->v.Slice.lower) { + start = s->v.Slice.lower->v.Constant.value; + } + PyObject *stop = NULL; + if (s->v.Slice.upper) { + stop = s->v.Slice.upper->v.Constant.value; + } + PyObject *step = NULL; + if (s->v.Slice.step) { + step = s->v.Slice.step->v.Constant.value; + } + PyObject *slice = PySlice_New(start, stop, step); + if (slice == NULL) { + return ERROR; + } + ADDOP_LOAD_CONST_NEW(c, LOC(s), slice); + return SUCCESS; + } + + RETURN_IF_ERROR(codegen_slice_two_parts(c, s)); + if (s->v.Slice.step) { n++; VISIT(c, expr, s->v.Slice.step); } - return n; + + ADDOP_I(c, LOC(s), BUILD_SLICE, n); + return SUCCESS; } diff --git a/Python/compile.c b/Python/compile.c index 9826d3fbbde976..d463fcde204a05 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1534,7 +1534,7 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, _PyCompile_CodeUnitMetadata *umd = &c->u->u_metadata; -#define SET_MATADATA_INT(key, value) do { \ +#define SET_METADATA_INT(key, value) do { \ PyObject *v = PyLong_FromLong((long)value); \ if (v == NULL) goto finally; \ int res = PyDict_SetItemString(metadata, key, v); \ @@ -1542,10 +1542,10 @@ _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, if (res < 0) goto finally; \ } while (0); - SET_MATADATA_INT("argcount", umd->u_argcount); - SET_MATADATA_INT("posonlyargcount", umd->u_posonlyargcount); - SET_MATADATA_INT("kwonlyargcount", umd->u_kwonlyargcount); -#undef SET_MATADATA_INT + SET_METADATA_INT("argcount", umd->u_argcount); + SET_METADATA_INT("posonlyargcount", umd->u_posonlyargcount); + SET_METADATA_INT("kwonlyargcount", umd->u_kwonlyargcount); +#undef SET_METADATA_INT int addNone = mod->kind != Expression_kind; if (_PyCodegen_AddReturnAtEnd(c, addNone) < 0) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 650bf4533a3a86..4574e183921006 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -14,9 +14,11 @@ case _CHECK_PERIODIC: { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) JUMP_TO_ERROR(); } break; @@ -28,7 +30,9 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); \ if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) JUMP_TO_ERROR(); } } @@ -62,10 +66,12 @@ oparg = CURRENT_OPARG(); _PyStackRef value_s = GETLOCAL(oparg); if (PyStackRef_IsNull(value_s)) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (1) JUMP_TO_ERROR(); } value = PyStackRef_DUP(value_s); @@ -323,11 +329,13 @@ case _END_SEND: { _PyStackRef value; _PyStackRef receiver; + _PyStackRef val; value = stack_pointer[-1]; receiver = stack_pointer[-2]; (void)receiver; + val = value; PyStackRef_CLOSE(receiver); - stack_pointer[-2] = value; + stack_pointer[-2] = val; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -337,7 +345,9 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); @@ -360,7 +370,9 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (err < 0) JUMP_TO_ERROR(); res = err ? PyStackRef_True : PyStackRef_False; @@ -469,7 +481,9 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); @@ -568,7 +582,7 @@ STAT_INC(BINARY_OP, hit); PyObject *res_o = _PyLong_Subtract((PyLongObject *)left_o, (PyLongObject *)right_o); _Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free);; + _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2] = res; @@ -775,7 +789,9 @@ container = stack_pointer[-2]; PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); PyObject *sub_o = PyStackRef_AsPyObjectBorrow(sub); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_GetItem(container_o, sub_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(container); PyStackRef_CLOSE(sub); if (res_o == NULL) JUMP_TO_ERROR(); @@ -794,8 +810,10 @@ stop = stack_pointer[-1]; start = stack_pointer[-2]; container = stack_pointer[-3]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), PyStackRef_AsPyObjectSteal(stop)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyObject *res_o; // Can't use ERROR_IF() here, because we haven't // DECREF'ed container yet, and we still own slice. @@ -803,8 +821,14 @@ res_o = NULL; } else { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(slice); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } PyStackRef_CLOSE(container); if (res_o == NULL) JUMP_TO_ERROR(); @@ -824,15 +848,23 @@ start = stack_pointer[-2]; container = stack_pointer[-3]; v = stack_pointer[-4]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), PyStackRef_AsPyObjectSteal(stop)); + stack_pointer = _PyFrame_GetStackPointer(frame); int err; if (slice == NULL) { err = 1; } else { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), slice, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(slice); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } PyStackRef_CLOSE(v); PyStackRef_CLOSE(container); @@ -976,9 +1008,13 @@ } STAT_INC(BINARY_SUBSCR, hit); PyObject *res_o; + _PyFrame_SetStackPointer(frame, stack_pointer); int rc = PyDict_GetItemRef(dict, sub, &res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (rc == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetKeyError(sub); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(dict_st); PyStackRef_CLOSE(sub_st); @@ -1031,13 +1067,11 @@ PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; PyObject *getitem = ht->_spec_cache.getitem; new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame); - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); new_frame->localsplus[0] = container; new_frame->localsplus[1] = sub; frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_BINARY_SUBSCR); - stack_pointer[0].bits = (uintptr_t)new_frame; - stack_pointer += 1; + stack_pointer[-2].bits = (uintptr_t)new_frame; + stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1048,8 +1082,9 @@ oparg = CURRENT_OPARG(); v = stack_pointer[-1]; list = stack_pointer[-2 - (oparg-1)]; - if (_PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), - PyStackRef_AsPyObjectSteal(v)) < 0) JUMP_TO_ERROR(); + int err = _PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), + PyStackRef_AsPyObjectSteal(v)); + if (err < 0) JUMP_TO_ERROR(); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -1061,8 +1096,10 @@ oparg = CURRENT_OPARG(); v = stack_pointer[-1]; set = stack_pointer[-2 - (oparg-1)]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); if (err) JUMP_TO_ERROR(); stack_pointer += -1; @@ -1078,7 +1115,9 @@ container = stack_pointer[-2]; v = stack_pointer[-3]; /* container[sub] = v */ + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); PyStackRef_CLOSE(container); PyStackRef_CLOSE(sub); @@ -1141,9 +1180,11 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(STORE_SUBSCR, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_SetItem_Take2((PyDictObject *)dict, PyStackRef_AsPyObjectSteal(sub), PyStackRef_AsPyObjectSteal(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(dict_st); if (err) JUMP_TO_ERROR(); stack_pointer += -3; @@ -1157,8 +1198,10 @@ sub = stack_pointer[-1]; container = stack_pointer[-2]; /* del container[sub] */ + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(container); PyStackRef_CLOSE(sub); if (err) JUMP_TO_ERROR(); @@ -1173,7 +1216,9 @@ oparg = CURRENT_OPARG(); value = stack_pointer[-1]; assert(oparg <= MAX_INTRINSIC_1); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); @@ -1191,7 +1236,9 @@ assert(oparg <= MAX_INTRINSIC_2); PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value2_st); PyStackRef_CLOSE(value1_st); if (res_o == NULL) JUMP_TO_ERROR(); @@ -1209,6 +1256,7 @@ #if TIER_ONE assert(frame != &entry_frame); #endif + _PyStackRef temp = retval; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -1218,9 +1266,9 @@ _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(frame->return_offset); - res = retval; + res = temp; LLTRACE_RESUME_FRAME(); stack_pointer[0] = res; stack_pointer += 1; @@ -1240,22 +1288,30 @@ getter = type->tp_as_async->am_aiter; } if (getter == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'async for' requires an object with " "__aiter__ method, got %.100s", type->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(obj); if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); iter_o = (*getter)(obj_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(obj); if (iter_o == NULL) JUMP_TO_ERROR(); if (Py_TYPE(iter_o)->tp_as_async == NULL || Py_TYPE(iter_o)->tp_as_async->am_anext == NULL) { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'async for' received an object from __aiter__ " "that does not implement __anext__: %.100s", Py_TYPE(iter_o)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(iter_o); if (true) JUMP_TO_ERROR(); } @@ -1268,7 +1324,9 @@ _PyStackRef aiter; _PyStackRef awaitable; aiter = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *awaitable_o = _PyEval_GetANext(PyStackRef_AsPyObjectBorrow(aiter)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (awaitable_o == NULL) { JUMP_TO_ERROR(); } @@ -1284,7 +1342,9 @@ _PyStackRef iter; oparg = CURRENT_OPARG(); iterable = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(iterable); if (iter_o == NULL) JUMP_TO_ERROR(); iter = PyStackRef_FromPyObjectSteal(iter_o); @@ -1339,6 +1399,7 @@ assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); assert(oparg == 0 || oparg == 1); gen->gi_frame_state = FRAME_SUSPENDED + oparg; + _PyStackRef temp = retval; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -1352,15 +1413,15 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || - frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); + frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); #endif + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - LOAD_SP(); - value = retval; + value = temp; LLTRACE_RESUME_FRAME(); stack_pointer[0] = value; stack_pointer += 1; @@ -1372,9 +1433,11 @@ _PyStackRef exc_value; exc_value = stack_pointer[-1]; _PyErr_StackItem *exc_info = tstate->exc_info; + _PyFrame_SetStackPointer(frame, stack_pointer); Py_XSETREF(exc_info->exc_value, PyStackRef_Is(exc_value, PyStackRef_None) ? NULL : PyStackRef_AsPyObjectSteal(exc_value)); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -1384,16 +1447,16 @@ _PyStackRef value; oparg = CURRENT_OPARG(); // Keep in sync with _common_constants in opcode.py - switch(oparg) { - case CONSTANT_ASSERTIONERROR: - value = PyStackRef_FromPyObjectImmortal(PyExc_AssertionError); - break; - case CONSTANT_NOTIMPLEMENTEDERROR: - value = PyStackRef_FromPyObjectImmortal(PyExc_NotImplementedError); - break; - default: - Py_FatalError("bad LOAD_COMMON_CONSTANT oparg"); + // If we ever have more than two constants, use a lookup table + PyObject *val; + if (oparg == CONSTANT_ASSERTIONERROR) { + val = PyExc_AssertionError; + } + else { + assert(oparg == CONSTANT_NOTIMPLEMENTEDERROR); + val = PyExc_NotImplementedError; } + value = PyStackRef_FromPyObjectImmortal(val); stack_pointer[0] = value; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -1403,10 +1466,15 @@ case _LOAD_BUILD_CLASS: { _PyStackRef bc; PyObject *bc_o; - if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o) < 0) JUMP_TO_ERROR(); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) JUMP_TO_ERROR(); if (bc_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_NameError, "__build_class__ not found"); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) JUMP_TO_ERROR(); } bc = PyStackRef_FromPyObjectSteal(bc_o); @@ -1424,15 +1492,23 @@ PyObject *ns = LOCALS(); int err; if (ns == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); if (true) JUMP_TO_ERROR(); } - if (PyDict_CheckExact(ns)) - err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); - else - err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + if (PyDict_CheckExact(ns)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } PyStackRef_CLOSE(v); if (err) JUMP_TO_ERROR(); stack_pointer += -1; @@ -1446,16 +1522,22 @@ PyObject *ns = LOCALS(); int err; if (ns == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_SystemError, "no locals when deleting %R", name); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_DelItem(ns, name); + stack_pointer = _PyFrame_GetStackPointer(frame); // Can't use ERROR_IF here. if (err != 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } break; @@ -1468,7 +1550,9 @@ seq = stack_pointer[-1]; output = &stack_pointer[-1]; _PyStackRef *top = output + oparg; + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg, -1, top); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(seq); if (res == 0) JUMP_TO_ERROR(); stack_pointer += -1 + oparg; @@ -1494,10 +1578,10 @@ } STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); - stack_pointer[0] = val0; val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); - stack_pointer[-1] = val1; PyStackRef_CLOSE(seq); + stack_pointer[-1] = val1; + stack_pointer[0] = val0; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; @@ -1562,7 +1646,9 @@ seq = stack_pointer[-1]; right = &stack_pointer[(oparg & 0xFF)]; _PyStackRef *top = right + (oparg >> 8); + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg & 0xFF, oparg >> 8, top); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(seq); if (res == 0) JUMP_TO_ERROR(); stack_pointer += (oparg & 0xFF) + (oparg >> 8); @@ -1577,8 +1663,10 @@ owner = stack_pointer[-1]; v = stack_pointer[-2]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetAttr(PyStackRef_AsPyObjectBorrow(owner), name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); PyStackRef_CLOSE(owner); if (err) JUMP_TO_ERROR(); @@ -1592,7 +1680,9 @@ oparg = CURRENT_OPARG(); owner = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelAttr(PyStackRef_AsPyObjectBorrow(owner), name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(owner); if (err) JUMP_TO_ERROR(); stack_pointer += -1; @@ -1605,7 +1695,9 @@ oparg = CURRENT_OPARG(); v = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_SetItem(GLOBALS(), name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); if (err) JUMP_TO_ERROR(); stack_pointer += -1; @@ -1616,14 +1708,18 @@ case _DELETE_GLOBAL: { oparg = CURRENT_OPARG(); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_Pop(GLOBALS(), name, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); // Can't use ERROR_IF here. if (err < 0) { JUMP_TO_ERROR(); } if (err == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } break; @@ -1633,8 +1729,10 @@ _PyStackRef locals; PyObject *l = LOCALS(); if (l == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_SystemError, "no locals found"); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) JUMP_TO_ERROR(); } locals = PyStackRef_FromPyObjectNew(l); @@ -1650,7 +1748,9 @@ _PyStackRef v; oparg = CURRENT_OPARG(); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *v_o = _PyEval_LoadName(tstate, frame, name); + stack_pointer = _PyFrame_GetStackPointer(frame); if (v_o == NULL) JUMP_TO_ERROR(); v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[0] = v; @@ -1665,7 +1765,9 @@ oparg = CURRENT_OPARG(); res = &stack_pointer[0]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res); + stack_pointer = _PyFrame_GetStackPointer(frame); if (PyStackRef_IsNull(*res)) JUMP_TO_ERROR(); null = PyStackRef_NULL; if (oparg & 1) stack_pointer[1] = null; @@ -1754,10 +1856,12 @@ oparg = CURRENT_OPARG(); _PyStackRef v = GETLOCAL(oparg); if (PyStackRef_IsNull(v)) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (1) JUMP_TO_ERROR(); } SETLOCAL(oparg, PyStackRef_NULL); @@ -1784,7 +1888,9 @@ // Fortunately we don't need its superpower. PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL); if (oldobj == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } Py_DECREF(oldobj); @@ -1802,7 +1908,9 @@ assert(class_dict); assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(class_dict, name, &value_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { JUMP_TO_ERROR(); } @@ -1810,7 +1918,9 @@ PyCellObject *cell = (PyCellObject *)PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); value_o = PyCell_GetRef(cell); if (value_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } } @@ -1826,7 +1936,9 @@ PyCellObject *cell = (PyCellObject *)PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); PyObject *value_o = PyCell_GetRef(cell); if (value_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) JUMP_TO_ERROR(); } value = PyStackRef_FromPyObjectSteal(value_o); @@ -1841,7 +1953,9 @@ oparg = CURRENT_OPARG(); v = stack_pointer[-1]; PyCellObject *cell = (PyCellObject *)PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); + _PyFrame_SetStackPointer(frame, stack_pointer); PyCell_SetTakeRef(cell, PyStackRef_AsPyObjectSteal(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -1924,16 +2038,22 @@ list_st = stack_pointer[-2 - (oparg-1)]; PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (none_val == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_TypeError); + stack_pointer = _PyFrame_GetStackPointer(frame); if (matches && (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Clear(tstate); _PyErr_Format(tstate, PyExc_TypeError, "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(iterable_st); if (true) JUMP_TO_ERROR(); @@ -1951,8 +2071,10 @@ oparg = CURRENT_OPARG(); iterable = stack_pointer[-1]; set = stack_pointer[-2 - (oparg-1)]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(iterable); if (err < 0) JUMP_TO_ERROR(); stack_pointer += -1; @@ -1965,7 +2087,9 @@ _PyStackRef set; oparg = CURRENT_OPARG(); values = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *set_o = PySet_New(NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); if (set_o == NULL) { for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(values[_i]); @@ -1975,7 +2099,9 @@ int err = 0; for (int i = 0; i < oparg; i++) { if (err == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); err = PySet_Add(set_o, PyStackRef_AsPyObjectBorrow(values[i])); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(values[i]); } @@ -2002,10 +2128,12 @@ } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *map_o = _PyDict_FromItems( values_o, 2, values_o+1, 2, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(values_o); for (int _i = oparg*2; --_i >= 0;) { PyStackRef_CLOSE(values[_i]); @@ -2019,20 +2147,28 @@ } case _SETUP_ANNOTATIONS: { - int err; PyObject *ann_dict; if (LOCALS() == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_SystemError, "no locals found when setting up annotations"); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) JUMP_TO_ERROR(); } /* check if __annotations__ in locals()... */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) JUMP_TO_ERROR(); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) JUMP_TO_ERROR(); if (ann_dict == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); ann_dict = PyDict_New(); + stack_pointer = _PyFrame_GetStackPointer(frame); if (ann_dict == NULL) JUMP_TO_ERROR(); + _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), ann_dict); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(ann_dict); if (err) JUMP_TO_ERROR(); } @@ -2050,13 +2186,19 @@ dict = stack_pointer[-2 - (oparg - 1)]; PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_Update(dict_o, update_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); + stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'%.200s' object is not a mapping", Py_TYPE(update_o)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(update); if (true) JUMP_TO_ERROR(); @@ -2078,9 +2220,13 @@ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_MergeEx(dict_o, update_o, 2); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatKwargsError(tstate, callable_o, update_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(update); if (true) JUMP_TO_ERROR(); } @@ -2102,11 +2248,13 @@ assert(PyDict_CheckExact(dict)); /* dict[key] = value */ // Do not DECREF INPUTS because the function steals the references + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_SetItem_Take2( (PyDictObject *)dict, PyStackRef_AsPyObjectSteal(key), PyStackRef_AsPyObjectSteal(value) ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) JUMP_TO_ERROR(); stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -2138,7 +2286,9 @@ } STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(global_super_st); PyStackRef_CLOSE(class_st); PyStackRef_CLOSE(self_st); @@ -2176,8 +2326,10 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyTypeObject *cls = (PyTypeObject *)class; int method_found = 0; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr_o = _PySuper_Lookup(cls, self, name, Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(global_super_st); PyStackRef_CLOSE(class_st); if (attr_o == NULL) { @@ -2209,7 +2361,9 @@ if (oparg & 1) { /* Designed to work in tandem with CALL, pushes two values. */ attr_o = NULL; + _PyFrame_SetStackPointer(frame, stack_pointer); int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (is_meth) { /* We can bypass temporary bound method object. meth is unbound method and obj is self. @@ -2232,9 +2386,13 @@ } else { /* Classic, pushes one value. */ + _PyFrame_SetStackPointer(frame, stack_pointer); attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(owner); if (attr_o == NULL) JUMP_TO_ERROR(); + /* We need to define self_or_null on all paths */ + self_or_null = PyStackRef_NULL; } attr = PyStackRef_FromPyObjectSteal(attr_o); stack_pointer[-1] = attr; @@ -2440,8 +2598,8 @@ STAT_INC(LOAD_ATTR, hit); null = PyStackRef_NULL; attr = PyStackRef_FromPyObjectNew(attr_o); - stack_pointer[-1] = attr; PyStackRef_CLOSE(owner); + stack_pointer[-1] = attr; break; } @@ -2462,8 +2620,8 @@ STAT_INC(LOAD_ATTR, hit); null = PyStackRef_NULL; attr = PyStackRef_FromPyObjectNew(attr_o); - stack_pointer[-1] = attr; PyStackRef_CLOSE(owner); + stack_pointer[-1] = attr; stack_pointer[0] = null; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -2499,9 +2657,9 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; null = PyStackRef_NULL; PyStackRef_CLOSE(owner); + stack_pointer[-1] = attr; break; } @@ -2515,9 +2673,9 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; null = PyStackRef_NULL; PyStackRef_CLOSE(owner); + stack_pointer[-1] = attr; stack_pointer[0] = null; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -2625,7 +2783,6 @@ JUMP_TO_JUMP_TARGET(); } PyObject *old_value; - uint64_t new_version; if (!DK_IS_UNICODE(dict->ma_keys)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -2641,9 +2798,10 @@ } old_value = ep->me_value; PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED; - new_version = _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value)); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); ep->me_value = PyStackRef_AsPyObjectSteal(value); - dict->ma_version_tag = new_version; // PEP 509 // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault, // when dict only holds the strong reference to value in ep->me_value. Py_XDECREF(old_value); @@ -2682,21 +2840,29 @@ PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); assert((oparg >> 5) <= Py_GE); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_RichCompare(left_o, right_o, oparg >> 5); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res_o == NULL) JUMP_TO_ERROR(); if (oparg & 16) { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int res_bool = PyObject_IsTrue(res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(res_o); if (res_bool < 0) JUMP_TO_ERROR(); res = res_bool ? PyStackRef_True : PyStackRef_False; } else { res = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); } - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -2816,7 +2982,9 @@ left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyFrame_SetStackPointer(frame, stack_pointer); int res = PySequence_Contains(right_o, left_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res < 0) JUMP_TO_ERROR(); @@ -2842,7 +3010,9 @@ } STAT_INC(CONTAINS_OP, hit); // Note: both set and frozenset use the same seq_contains method! + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PySet_Contains((PySetObject *)right_o, left_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res < 0) JUMP_TO_ERROR(); @@ -2867,7 +3037,9 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CONTAINS_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyDict_Contains(right_o, left_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res < 0) JUMP_TO_ERROR(); @@ -2887,7 +3059,9 @@ exc_value_st = stack_pointer[-2]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); PyObject *match_type = PyStackRef_AsPyObjectBorrow(match_type_st); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyEval_CheckExceptStarTypeValid(tstate, match_type); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { PyStackRef_CLOSE(exc_value_st); PyStackRef_CLOSE(match_type_st); @@ -2895,15 +3069,23 @@ } PyObject *match_o = NULL; PyObject *rest_o = NULL; + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_ExceptionGroupMatch(exc_value, match_type, &match_o, &rest_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(exc_value_st); PyStackRef_CLOSE(match_type_st); if (res < 0) JUMP_TO_ERROR(); assert((match_o == NULL) == (rest_o == NULL)); if (match_o == NULL) JUMP_TO_ERROR(); if (!Py_IsNone(match_o)) { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyErr_SetHandledException(match_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } rest = PyStackRef_FromPyObjectSteal(rest_o); match = PyStackRef_FromPyObjectSteal(match_o); @@ -2921,12 +3103,16 @@ PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); assert(PyExceptionInstance_Check(left_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyEval_CheckExceptTypeValid(tstate, right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { PyStackRef_CLOSE(right); if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyErr_GivenExceptionMatches(left_o, right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(right); b = res ? PyStackRef_True : PyStackRef_False; stack_pointer[-1] = b; @@ -2941,9 +3127,11 @@ fromlist = stack_pointer[-1]; level = stack_pointer[-2]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_ImportName(tstate, frame, name, PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(level); PyStackRef_CLOSE(fromlist); if (res_o == NULL) JUMP_TO_ERROR(); @@ -2960,7 +3148,9 @@ oparg = CURRENT_OPARG(); from = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; @@ -2993,7 +3183,9 @@ _PyStackRef len; obj = stack_pointer[-1]; // PUSH(len(TOS)) + _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(PyStackRef_AsPyObjectBorrow(obj)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (len_i < 0) JUMP_TO_ERROR(); PyObject *len_o = PyLong_FromSsize_t(len_i); if (len_o == NULL) JUMP_TO_ERROR(); @@ -3016,10 +3208,12 @@ // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attrs_o = _PyEval_MatchClass(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(subject); PyStackRef_CLOSE(type); PyStackRef_CLOSE(names); @@ -3069,8 +3263,10 @@ keys = stack_pointer[-1]; subject = stack_pointer[-2]; // On successful match, PUSH(values). Otherwise, PUSH(None). + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *values_or_none_o = _PyEval_MatchKeys(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(keys)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (values_or_none_o == NULL) JUMP_TO_ERROR(); values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o); stack_pointer[0] = values_or_none; @@ -3084,9 +3280,12 @@ _PyStackRef iter; iterable = stack_pointer[-1]; /* before: [obj]; after [getiter(obj)] */ - iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable))); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(iterable); - if (PyStackRef_IsNull(iter)) JUMP_TO_ERROR(); + if (iter_o == NULL) JUMP_TO_ERROR(); + iter = PyStackRef_FromPyObjectSteal(iter_o); stack_pointer[-1] = iter; break; } @@ -3102,23 +3301,29 @@ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } iter = iterable; } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } else { - /* `iterable` is not a generator. */ - iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o)); - if (PyStackRef_IsNull(iter)) { - JUMP_TO_ERROR(); + if (PyGen_CheckExact(iterable_o)) { + iter = iterable; + } + else { + /* `iterable` is not a generator. */ + _PyFrame_SetStackPointer(frame, stack_pointer); + iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsNull(iter)) { + JUMP_TO_ERROR(); + } + PyStackRef_CLOSE(iterable); } - PyStackRef_CLOSE(iterable); } stack_pointer[-1] = iter; break; @@ -3132,15 +3337,21 @@ iter = stack_pointer[-1]; /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (next_o == NULL) { if (_PyErr_Occurred(tstate)) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); if (!matches) { JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_MonitorRaise(tstate, frame, frame->instr_ptr); _PyErr_Clear(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); } /* iterator ended normally */ /* The translator sets the deopt target just past the matching END_FOR */ @@ -3339,19 +3550,27 @@ PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner); PyObject *name = _Py_SpecialMethods[oparg].name; PyObject *self_or_null_o; - attr = PyStackRef_FromPyObjectSteal(_PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o)); - if (PyStackRef_IsNull(attr)) { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (attr_o == NULL) { if (!_PyErr_Occurred(tstate)) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, _Py_SpecialMethods[oparg].error, Py_TYPE(owner_o)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); } + if (true) JUMP_TO_ERROR(); } - if (PyStackRef_IsNull(attr)) JUMP_TO_ERROR(); - self_or_null = PyStackRef_FromPyObjectSteal(self_or_null_o); - stack_pointer[-1] = attr; - stack_pointer[0] = self_or_null; - stack_pointer += 1; + attr = PyStackRef_FromPyObjectSteal(attr_o); + self_or_null = self_or_null_o == NULL ? + PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o); + stack_pointer[0] = attr; + stack_pointer[1] = self_or_null; + stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); break; } @@ -3391,9 +3610,12 @@ (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb}; int has_self = !PyStackRef_IsNull(exit_self); - res = PyStackRef_FromPyObjectSteal(PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, - (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL)); - if (PyStackRef_IsNull(res)) JUMP_TO_ERROR(); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, + (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) JUMP_TO_ERROR(); + res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -3401,9 +3623,10 @@ } case _PUSH_EXC_INFO: { - _PyStackRef new_exc; + _PyStackRef exc; _PyStackRef prev_exc; - new_exc = stack_pointer[-1]; + _PyStackRef new_exc; + exc = stack_pointer[-1]; _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { prev_exc = PyStackRef_FromPyObjectSteal(exc_info->exc_value); @@ -3411,8 +3634,9 @@ else { prev_exc = PyStackRef_None; } - assert(PyStackRef_ExceptionInstanceCheck(new_exc)); - exc_info->exc_value = PyStackRef_AsPyObjectNew(new_exc); + assert(PyStackRef_ExceptionInstanceCheck(exc)); + exc_info->exc_value = PyStackRef_AsPyObjectNew(exc); + new_exc = exc; stack_pointer[-1] = prev_exc; stack_pointer[0] = new_exc; stack_pointer += 1; @@ -3458,8 +3682,8 @@ assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; self = owner; + stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -3479,8 +3703,8 @@ assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; self = owner; + stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -3544,8 +3768,8 @@ assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; self = owner; + stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -3555,25 +3779,23 @@ case _MAYBE_EXPAND_METHOD: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; - _PyStackRef func; + _PyStackRef *callable; + _PyStackRef *func; _PyStackRef *maybe_self; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; + func = &stack_pointer[-2 - oparg]; maybe_self = &stack_pointer[-1 - oparg]; - if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *self = ((PyMethodObject *)callable_o)->im_self; maybe_self[0] = PyStackRef_FromPyObjectNew(self); PyObject *method = ((PyMethodObject *)callable_o)->im_func; - func = PyStackRef_FromPyObjectNew(method); - stack_pointer[-2 - oparg] = func; - PyStackRef_CLOSE(callable); - } - else { - func = callable; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); } break; } @@ -3585,13 +3807,13 @@ case _PY_FRAME_GENERAL: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3601,17 +3823,19 @@ assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); - new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyInterpreterFrame *temp = _PyEvalFramePushAndInit( + tstate, callable[0], locals, args, total_args, NULL, frame ); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. + stack_pointer = _PyFrame_GetStackPointer(frame); + // The frame has stolen all the arguments from the stack. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); - if (new_frame == NULL) { + if (temp == NULL) { JUMP_TO_ERROR(); } + new_frame = temp; stack_pointer[0].bits = (uintptr_t)new_frame; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -3619,11 +3843,11 @@ } case _CHECK_FUNCTION_VERSION: { - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; uint32_t func_version = (uint32_t)CURRENT_OPERAND(); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); if (!PyFunction_Check(callable_o)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -3638,12 +3862,12 @@ case _CHECK_METHOD_VERSION: { _PyStackRef *null; - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; uint32_t func_version = (uint32_t)CURRENT_OPERAND(); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); if (Py_TYPE(callable_o) != &PyMethod_Type) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -3666,29 +3890,30 @@ case _EXPAND_METHOD: { _PyStackRef *null; - _PyStackRef callable; - _PyStackRef method; + _PyStackRef *callable; + _PyStackRef *method; _PyStackRef *self; oparg = CURRENT_OPARG(); null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; + method = &stack_pointer[-2 - oparg]; self = &stack_pointer[-1 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyStackRef_IsNull(null[0])); assert(Py_TYPE(callable_o) == &PyMethod_Type); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - stack_pointer[-2 - oparg] = method; - assert(PyStackRef_FunctionCheck(method)); - PyStackRef_CLOSE(callable); + _PyStackRef temp = callable[0]; + method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + assert(PyStackRef_FunctionCheck(method[0])); + PyStackRef_CLOSE(temp); break; } case _CHECK_IS_NOT_PY_CALLABLE: { - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); if (PyFunction_Check(callable_o)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -3703,16 +3928,16 @@ case _CALL_NON_PY_GENERAL: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; #if TIER_ONE assert(opcode != INSTRUMENTED_CALL); #endif - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -3721,20 +3946,22 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -3748,15 +3975,15 @@ case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: { _PyStackRef *null; - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; if (!PyStackRef_IsNull(null[0])) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - if (Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type) { + if (Py_TYPE(PyStackRef_AsPyObjectBorrow(callable[0])) != &PyMethod_Type) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } @@ -3764,18 +3991,21 @@ } case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: { - _PyStackRef callable; - _PyStackRef func; + _PyStackRef *null; + _PyStackRef *callable; + _PyStackRef *func; _PyStackRef *self; oparg = CURRENT_OPARG(); - callable = stack_pointer[-2 - oparg]; + null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + func = &stack_pointer[-2 - oparg]; self = &stack_pointer[-1 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); STAT_INC(CALL, hit); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - stack_pointer[-2 - oparg] = func; - PyStackRef_CLOSE(callable); + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + PyStackRef_CLOSE(temp); break; } @@ -3789,11 +4019,11 @@ case _CHECK_FUNCTION_EXACT_ARGS: { _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyFunction_Check(callable_o)); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; @@ -3805,10 +4035,10 @@ } case _CHECK_STACK_SPACE: { - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { @@ -3825,16 +4055,16 @@ case _INIT_CALL_PY_EXACT_ARGS_0: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = 0; assert(oparg == CURRENT_OPARG()); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -3849,16 +4079,16 @@ case _INIT_CALL_PY_EXACT_ARGS_1: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = 1; assert(oparg == CURRENT_OPARG()); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -3873,16 +4103,16 @@ case _INIT_CALL_PY_EXACT_ARGS_2: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = 2; assert(oparg == CURRENT_OPARG()); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -3897,16 +4127,16 @@ case _INIT_CALL_PY_EXACT_ARGS_3: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = 3; assert(oparg == CURRENT_OPARG()); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -3921,16 +4151,16 @@ case _INIT_CALL_PY_EXACT_ARGS_4: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = 4; assert(oparg == CURRENT_OPARG()); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -3945,15 +4175,15 @@ case _INIT_CALL_PY_EXACT_ARGS: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -3971,12 +4201,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -4034,7 +4265,9 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); res = PyStackRef_FromPyObjectSteal(PyObject_Str(arg_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(arg); if (PyStackRef_IsNull(res)) JUMP_TO_ERROR(); stack_pointer[-3] = res; @@ -4064,7 +4297,9 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); res = PyStackRef_FromPyObjectSteal(PySequence_Tuple(arg_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(arg); if (PyStackRef_IsNull(res)) JUMP_TO_ERROR(); stack_pointer[-3] = res; @@ -4075,17 +4310,19 @@ case _CHECK_AND_ALLOCATE_OBJECT: { _PyStackRef *args; - _PyStackRef null; - _PyStackRef callable; - _PyStackRef self; - _PyStackRef init; + _PyStackRef *null; + _PyStackRef *callable; + _PyStackRef *init; + _PyStackRef *self; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + init = &stack_pointer[-2 - oparg]; + self = &stack_pointer[-1 - oparg]; uint32_t type_version = (uint32_t)CURRENT_OPERAND(); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - if (!PyStackRef_IsNull(null)) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); + if (!PyStackRef_IsNull(null[0])) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } @@ -4107,35 +4344,39 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); - self = PyStackRef_FromPyObjectSteal(_PyType_NewManagedObject(tp)); - if (PyStackRef_IsNull(self)) { + PyObject *self_o = _PyType_NewManagedObject(tp); + if (self_o == NULL) { JUMP_TO_ERROR(); } - PyStackRef_CLOSE(callable); - init = PyStackRef_FromPyObjectNew(init_func); - stack_pointer[-1 - oparg] = init; - stack_pointer[-2 - oparg] = self; + self[0] = PyStackRef_FromPyObjectSteal(self_o); + _PyStackRef temp = callable[0]; + init[0] = PyStackRef_FromPyObjectNew(init_func); + PyStackRef_CLOSE(temp); break; } case _CREATE_INIT_FRAME: { _PyStackRef *args; - _PyStackRef init; - _PyStackRef self; + _PyStackRef *self; + _PyStackRef *init; _PyInterpreterFrame *init_frame; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; - init = stack_pointer[-1 - oparg]; - self = stack_pointer[-2 - oparg]; + self = &stack_pointer[-1 - oparg]; + init = &stack_pointer[-2 - oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( tstate, (PyCodeObject *)&_Py_InitCleanup, 1, frame); + stack_pointer = _PyFrame_GetStackPointer(frame); assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK); /* Push self onto stack of shim */ - shim->localsplus[0] = PyStackRef_DUP(self); - args[-1] = self; + shim->localsplus[0] = PyStackRef_DUP(self[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); init_frame = _PyEvalFramePushAndInit( - tstate, init, NULL, args-1, oparg+1, NULL, shim); - stack_pointer += -2 - oparg; + tstate, init[0], NULL, args-1, oparg+1, NULL, shim); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-2 - oparg].bits = (uintptr_t)init_frame; + stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); if (init_frame == NULL) { _PyEval_FrameClearAndPop(tstate, shim); @@ -4146,9 +4387,6 @@ * We don't check recursion depth here, * as it will be checked after start_frame */ tstate->py_recursion_remaining--; - stack_pointer[0].bits = (uintptr_t)init_frame; - stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -4157,9 +4395,11 @@ should_be_none = stack_pointer[-1]; assert(STACK_LEVEL() == 2); if (!PyStackRef_Is(should_be_none, PyStackRef_None)) { + _PyFrame_SetStackPointer(frame, stack_pointer); PyErr_Format(PyExc_TypeError, "__init__() should return None, not '%.200s'", Py_TYPE(PyStackRef_AsPyObjectBorrow(should_be_none))->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } stack_pointer += -1; @@ -4170,13 +4410,13 @@ case _CALL_BUILTIN_CLASS: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4194,20 +4434,22 @@ STAT_INC(CALL, hit); STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = tp->tp_vectorcall((PyObject *)tp, args_o, total_args, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4219,14 +4461,14 @@ case _CALL_BUILTIN_O: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* Builtin METH_O functions */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4253,11 +4495,13 @@ PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; _Py_EnterRecursiveCallTstateUnchecked(tstate); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable_o), PyStackRef_AsPyObjectBorrow(arg)); + stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(arg); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4269,14 +4513,14 @@ case _CALL_BUILTIN_FAST: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* Builtin METH_FASTCALL functions, without keywords */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4295,24 +4539,26 @@ /* res = func(self, args, nargs) */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = ((PyCFunctionFast)(void(*)(void))cfunc)( PyCFunction_GET_SELF(callable_o), args_o, total_args); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4324,14 +4570,14 @@ case _CALL_BUILTIN_FAST_WITH_KEYWORDS: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4347,26 +4593,30 @@ } STAT_INC(CALL, hit); /* res = func(self, args, nargs, kwnames) */ + _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = (PyCFunctionFastWithKeywords)(void(*)(void)) PyCFunction_GET_FUNCTION(callable_o); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = cfunc(PyCFunction_GET_SELF(callable_o), args_o, total_args, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4378,14 +4628,14 @@ case _CALL_LEN: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* len(o) */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4403,7 +4653,9 @@ STAT_INC(CALL, hit); _PyStackRef arg_stackref = args[0]; PyObject *arg = PyStackRef_AsPyObjectBorrow(arg_stackref); + _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (len_i < 0) { JUMP_TO_ERROR(); } @@ -4412,7 +4664,7 @@ if (res_o == NULL) { GOTO_ERROR(error); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(arg_stackref); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4424,14 +4676,14 @@ case _CALL_ISINSTANCE: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* isinstance(o, o2) */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4449,7 +4701,9 @@ STAT_INC(CALL, hit); _PyStackRef cls_stackref = args[1]; _PyStackRef inst_stackref = args[0]; + _PyFrame_SetStackPointer(frame, stack_pointer); int retval = PyObject_IsInstance(PyStackRef_AsPyObjectBorrow(inst_stackref), PyStackRef_AsPyObjectBorrow(cls_stackref)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (retval < 0) { JUMP_TO_ERROR(); } @@ -4457,7 +4711,7 @@ assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(inst_stackref); PyStackRef_CLOSE(cls_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -4504,13 +4758,13 @@ case _CALL_METHOD_DESCRIPTOR_O: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4545,14 +4799,16 @@ STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; _Py_EnterRecursiveCallTstateUnchecked(tstate); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyStackRef_AsPyObjectBorrow(self_stackref), PyStackRef_AsPyObjectBorrow(arg_stackref)); + stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(self_stackref); PyStackRef_CLOSE(arg_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4564,13 +4820,13 @@ case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4594,25 +4850,27 @@ } STAT_INC(CALL, hit); int nargs = total_args - 1; - PyCFunctionFastWithKeywords cfunc = - (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFastWithKeywords cfunc = + (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; PyObject *res_o = cfunc(self, (args_o + 1), nargs, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4624,14 +4882,14 @@ case _CALL_METHOD_DESCRIPTOR_NOARGS: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; assert(oparg == 0 || oparg == 1); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4665,11 +4923,13 @@ STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; _Py_EnterRecursiveCallTstateUnchecked(tstate); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(self_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4681,13 +4941,13 @@ case _CALL_METHOD_DESCRIPTOR_FAST: { _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4710,26 +4970,28 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); - PyCFunctionFast cfunc = - (PyCFunctionFast)(void(*)(void))meth->ml_meth; int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); } if (true) JUMP_TO_ERROR(); } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFast cfunc = + (PyCFunctionFast)(void(*)(void))meth->ml_meth; PyObject *res_o = cfunc(self, (args_o + 1), nargs); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Clear the stack of the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -4740,20 +5002,49 @@ /* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 because it is instrumented */ + case _MAYBE_EXPAND_METHOD_KW: { + _PyStackRef kwnames_in; + _PyStackRef *args; + _PyStackRef *self_or_null; + _PyStackRef *callable; + _PyStackRef *func; + _PyStackRef *maybe_self; + _PyStackRef kwnames_out; + oparg = CURRENT_OPARG(); + kwnames_in = stack_pointer[-1]; + args = &stack_pointer[-1 - oparg]; + self_or_null = &stack_pointer[-2 - oparg]; + callable = &stack_pointer[-3 - oparg]; + func = &stack_pointer[-3 - oparg]; + maybe_self = &stack_pointer[-2 - oparg]; + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); + PyObject *self = ((PyMethodObject *)callable_o)->im_self; + maybe_self[0] = PyStackRef_FromPyObjectNew(self); + PyObject *method = ((PyMethodObject *)callable_o)->im_func; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); + } + kwnames_out = kwnames_in; + stack_pointer[-1] = kwnames_out; + break; + } + /* _DO_CALL_KW is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ case _PY_FRAME_KW: { _PyStackRef kwnames; _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyInterpreterFrame *new_frame; oparg = CURRENT_OPARG(); kwnames = stack_pointer[-1]; args = &stack_pointer[-1 - oparg]; self_or_null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-3 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -4765,30 +5056,30 @@ assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, positional_args, kwnames_o, frame ); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(kwnames); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. - stack_pointer += -3 - oparg; + stack_pointer[-3 - oparg].bits = (uintptr_t)new_frame; + stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (new_frame == NULL) { JUMP_TO_ERROR(); } - stack_pointer[0].bits = (uintptr_t)new_frame; - stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); break; } case _CHECK_FUNCTION_VERSION_KW: { - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); - callable = stack_pointer[-3 - oparg]; + callable = &stack_pointer[-3 - oparg]; uint32_t func_version = (uint32_t)CURRENT_OPERAND(); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); if (!PyFunction_Check(callable_o)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4803,12 +5094,12 @@ case _CHECK_METHOD_VERSION_KW: { _PyStackRef *null; - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; + callable = &stack_pointer[-3 - oparg]; uint32_t func_version = (uint32_t)CURRENT_OPERAND(); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); if (Py_TYPE(callable_o) != &PyMethod_Type) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4830,33 +5121,31 @@ } case _EXPAND_METHOD_KW: { - _PyStackRef kwnames; _PyStackRef *null; - _PyStackRef callable; - _PyStackRef method; + _PyStackRef *callable; + _PyStackRef *method; _PyStackRef *self; oparg = CURRENT_OPARG(); - kwnames = stack_pointer[-1]; null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; + callable = &stack_pointer[-3 - oparg]; + method = &stack_pointer[-3 - oparg]; self = &stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + _PyStackRef callable_s = callable[0]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable_s); assert(PyStackRef_IsNull(null[0])); assert(Py_TYPE(callable_o) == &PyMethod_Type); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - stack_pointer[-3 - oparg] = method; - assert(PyStackRef_FunctionCheck(method)); - PyStackRef_CLOSE(callable); - stack_pointer[-1] = kwnames; + method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + assert(PyStackRef_FunctionCheck(method[0])); + PyStackRef_CLOSE(callable_s); break; } case _CHECK_IS_NOT_PY_CALLABLE_KW: { - _PyStackRef callable; + _PyStackRef *callable; oparg = CURRENT_OPARG(); - callable = stack_pointer[-3 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-3 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); if (PyFunction_Check(callable_o)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4872,17 +5161,17 @@ _PyStackRef kwnames; _PyStackRef *args; _PyStackRef *self_or_null; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef res; oparg = CURRENT_OPARG(); kwnames = stack_pointer[-1]; args = &stack_pointer[-1 - oparg]; self_or_null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; + callable = &stack_pointer[-3 - oparg]; #if TIER_ONE assert(opcode != INSTRUMENTED_CALL); #endif - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4891,7 +5180,7 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -4901,17 +5190,19 @@ } PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(kwnames); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) JUMP_TO_ERROR(); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-3 - oparg] = res; @@ -4922,19 +5213,55 @@ /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it is instrumented */ - /* __DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ + case _MAKE_CALLARGS_A_TUPLE: { + _PyStackRef kwargs_in = PyStackRef_NULL; + _PyStackRef callargs; + _PyStackRef func; + _PyStackRef tuple; + _PyStackRef kwargs_out = PyStackRef_NULL; + oparg = CURRENT_OPARG(); + if (oparg & 1) { kwargs_in = stack_pointer[-(oparg & 1)]; } + callargs = stack_pointer[-1 - (oparg & 1)]; + func = stack_pointer[-3 - (oparg & 1)]; + PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs); + if (PyTuple_CheckExact(callargs_o)) { + tuple = callargs; + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) { + JUMP_TO_ERROR(); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *tuple_o = PySequence_Tuple(callargs_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (tuple_o == NULL) { + JUMP_TO_ERROR(); + } + PyStackRef_CLOSE(callargs); + tuple = PyStackRef_FromPyObjectSteal(tuple_o); + } + kwargs_out = kwargs_in; + stack_pointer[-1 - (oparg & 1)] = tuple; + if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out; + break; + } + + /* _DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ case _MAKE_FUNCTION: { _PyStackRef codeobj_st; _PyStackRef func; codeobj_st = stack_pointer[-1]; PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(codeobj_st); - if (func_obj == NULL) { - JUMP_TO_ERROR(); - } + if (func_obj == NULL) JUMP_TO_ERROR(); _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); @@ -4943,43 +5270,22 @@ } case _SET_FUNCTION_ATTRIBUTE: { - _PyStackRef func_st; + _PyStackRef func_in; _PyStackRef attr_st; + _PyStackRef func_out; oparg = CURRENT_OPARG(); - func_st = stack_pointer[-1]; + func_in = stack_pointer[-1]; attr_st = stack_pointer[-2]; - PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - PyObject *attr = PyStackRef_AsPyObjectBorrow(attr_st); + PyObject *func = PyStackRef_AsPyObjectBorrow(func_in); + PyObject *attr = PyStackRef_AsPyObjectSteal(attr_st); + func_out = func_in; assert(PyFunction_Check(func)); - PyFunctionObject *func_obj = (PyFunctionObject *)func; - switch(oparg) { - case MAKE_FUNCTION_CLOSURE: - assert(func_obj->func_closure == NULL); - func_obj->func_closure = attr; - break; - case MAKE_FUNCTION_ANNOTATIONS: - assert(func_obj->func_annotations == NULL); - func_obj->func_annotations = attr; - break; - case MAKE_FUNCTION_KWDEFAULTS: - assert(PyDict_CheckExact(attr)); - assert(func_obj->func_kwdefaults == NULL); - func_obj->func_kwdefaults = attr; - break; - case MAKE_FUNCTION_DEFAULTS: - assert(PyTuple_CheckExact(attr)); - assert(func_obj->func_defaults == NULL); - func_obj->func_defaults = attr; - break; - case MAKE_FUNCTION_ANNOTATE: - assert(PyCallable_Check(attr)); - assert(func_obj->func_annotate == NULL); - func_obj->func_annotate = attr; - break; - default: - Py_UNREACHABLE(); - } - stack_pointer[-2] = func_st; + size_t offset = _Py_FunctionAttributeOffsets[oparg]; + assert(offset != 0); + PyObject **ptr = (PyObject **)(((char *)func) + offset); + assert(*ptr == NULL); + *ptr = attr; + stack_pointer[-2] = func_out; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -4989,10 +5295,10 @@ _PyStackRef res; assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); + _PyFrame_SetStackPointer(frame, stack_pointer); PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - if (gen == NULL) { - JUMP_TO_ERROR(); - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (gen == NULL) JUMP_TO_ERROR(); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *gen_frame = &gen->gi_iframe; @@ -5002,12 +5308,12 @@ gen->gi_frame_state = FRAME_CREATED; gen_frame->owner = FRAME_OWNED_BY_GENERATOR; _Py_LeaveRecursiveCallPy(tstate); - res = PyStackRef_FromPyObjectSteal((PyObject *)gen); _PyInterpreterFrame *prev = frame->previous; _PyThreadState_PopFrame(tstate, frame); frame = tstate->current_frame = prev; LOAD_IP(frame->return_offset); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); + res = PyStackRef_FromPyObjectSteal((PyObject *)gen); LLTRACE_RESUME_FRAME(); stack_pointer[0] = res; stack_pointer += 1; @@ -5047,7 +5353,9 @@ conversion_func conv_fn; assert(oparg >= FVC_STR && oparg <= FVC_ASCII); conv_fn = _PyEval_ConversionFuncs[oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *result_o = conv_fn(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (result_o == NULL) JUMP_TO_ERROR(); result = PyStackRef_FromPyObjectSteal(result_o); @@ -5063,9 +5371,12 @@ /* If value is a unicode object, then we know the result * of format(value) is value itself. */ if (!PyUnicode_CheckExact(value_o)) { - res = PyStackRef_FromPyObjectSteal(PyObject_Format(value_o, NULL)); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = PyObject_Format(value_o, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); - if (PyStackRef_IsNull(res)) JUMP_TO_ERROR(); + if (res_o == NULL) JUMP_TO_ERROR(); + res = PyStackRef_FromPyObjectSteal(res_o); } else { res = value; @@ -5080,7 +5391,9 @@ _PyStackRef res; fmt_spec = stack_pointer[-1]; value = stack_pointer[-2]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Format(PyStackRef_AsPyObjectBorrow(value), PyStackRef_AsPyObjectBorrow(fmt_spec)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); PyStackRef_CLOSE(fmt_spec); if (res_o == NULL) JUMP_TO_ERROR(); @@ -5114,7 +5427,9 @@ PyObject *lhs_o = PyStackRef_AsPyObjectBorrow(lhs); PyObject *rhs_o = PyStackRef_AsPyObjectBorrow(rhs); assert(_PyEval_BinaryOps[oparg]); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_BinaryOps[oparg](lhs_o, rhs_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(lhs); PyStackRef_CLOSE(rhs); if (res_o == NULL) JUMP_TO_ERROR(); @@ -5126,14 +5441,18 @@ } case _SWAP: { - _PyStackRef top; - _PyStackRef bottom; + _PyStackRef top_in; + _PyStackRef bottom_in; + _PyStackRef top_out; + _PyStackRef bottom_out; oparg = CURRENT_OPARG(); - top = stack_pointer[-1]; - bottom = stack_pointer[-2 - (oparg-2)]; + top_in = stack_pointer[-1]; + bottom_in = stack_pointer[-2 - (oparg-2)]; + bottom_out = bottom_in; + top_out = top_in; assert(oparg >= 2); - stack_pointer[-2 - (oparg-2)] = top; - stack_pointer[-1] = bottom; + stack_pointer[-2 - (oparg-2)] = top_out; + stack_pointer[-1] = bottom_out; break; } @@ -5156,54 +5475,58 @@ case _GUARD_IS_TRUE_POP: { _PyStackRef flag; flag = stack_pointer[-1]; + int is_true = PyStackRef_Is(flag, PyStackRef_True); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); - if (!PyStackRef_Is(flag, PyStackRef_True)) { + if (!is_true) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - assert(PyStackRef_Is(flag, PyStackRef_True)); break; } case _GUARD_IS_FALSE_POP: { _PyStackRef flag; flag = stack_pointer[-1]; + int is_false = PyStackRef_Is(flag, PyStackRef_False); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); - if (!PyStackRef_Is(flag, PyStackRef_False)) { + if (!is_false) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - assert(PyStackRef_Is(flag, PyStackRef_False)); break; } case _GUARD_IS_NONE_POP: { _PyStackRef val; val = stack_pointer[-1]; - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); - if (!PyStackRef_Is(val, PyStackRef_None)) { + int is_none = PyStackRef_Is(val, PyStackRef_None); + if (!is_none) { PyStackRef_CLOSE(val); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); if (1) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); break; } case _GUARD_IS_NOT_NONE_POP: { _PyStackRef val; val = stack_pointer[-1]; + int is_none = PyStackRef_Is(val, PyStackRef_None); + PyStackRef_CLOSE(val); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); - if (PyStackRef_Is(val, PyStackRef_None)) { + if (is_none) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - PyStackRef_CLOSE(val); break; } @@ -5251,12 +5574,14 @@ #if defined(Py_DEBUG) && !defined(_Py_JIT) OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); if (lltrace >= 2) { + _PyFrame_SetStackPointer(frame, stack_pointer); printf("SIDE EXIT: [UOp "); _PyUOpPrint(&next_uop[-1]); printf(", exit %u, temp %d, target %d -> %s]\n", - exit - current_executor->exits, exit->temperature.as_counter, + exit - current_executor->exits, exit->temperature.value_and_backoff, (int)(target - _PyCode_CODE(code)), _PyOpcode_OpName[target->op.code]); + stack_pointer = _PyFrame_GetStackPointer(frame); } #endif if (exit->executor && !exit->executor->vm_data.valid) { @@ -5277,7 +5602,9 @@ } else { int chain_depth = current_executor->vm_data.chain_depth + 1; + _PyFrame_SetStackPointer(frame, stack_pointer); int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth); + stack_pointer = _PyFrame_GetStackPointer(frame); if (optimized <= 0) { exit->temperature = restart_backoff_counter(temperature); if (optimized < 0) { @@ -5339,8 +5666,8 @@ _PyStackRef null; PyObject *ptr = (PyObject *)CURRENT_OPERAND(); value = PyStackRef_FromPyObjectNew(ptr); - stack_pointer[0] = value; null = PyStackRef_NULL; + stack_pointer[0] = value; stack_pointer[1] = null; stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); @@ -5389,12 +5716,14 @@ #if defined(Py_DEBUG) && !defined(_Py_JIT) OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); if (lltrace >= 2) { + _PyFrame_SetStackPointer(frame, stack_pointer); printf("DYNAMIC EXIT: [UOp "); _PyUOpPrint(&next_uop[-1]); printf(", exit %u, temp %d, target %d -> %s]\n", - exit - current_executor->exits, exit->temperature.as_counter, + exit - current_executor->exits, exit->temperature.value_and_backoff, (int)(target - _PyCode_CODE(_PyFrame_GetCode(frame))), _PyOpcode_OpName[target->op.code]); + stack_pointer = _PyFrame_GetStackPointer(frame); } #endif _PyExecutorObject *executor; @@ -5408,7 +5737,9 @@ exit->temperature = advance_backoff_counter(exit->temperature); GOTO_TIER_ONE(target); } + _PyFrame_SetStackPointer(frame, stack_pointer); int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, 0); + stack_pointer = _PyFrame_GetStackPointer(frame); if (optimized <= 0) { exit->temperature = restart_backoff_counter(exit->temperature); if (optimized < 0) { diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 69d7e0a872aa48..388862912d6826 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1001,13 +1001,14 @@ remove_unreachable(basicblock *entryblock) { basicblock **sp = stack; entryblock->b_predecessors = 1; *sp++ = entryblock; + entryblock->b_visited = 1; while (sp > stack) { basicblock *b = *(--sp); - b->b_visited = 1; if (b->b_next && BB_HAS_FALLTHROUGH(b)) { if (!b->b_next->b_visited) { assert(b->b_next->b_predecessors == 0); *sp++ = b->b_next; + b->b_next->b_visited = 1; } b->b_next->b_predecessors++; } @@ -1017,8 +1018,8 @@ remove_unreachable(basicblock *entryblock) { if (is_jump(instr) || is_block_push(instr)) { target = instr->i_target; if (!target->b_visited) { - assert(target->b_predecessors == 0 || target == b->b_next); *sp++ = target; + target->b_visited = 1; } target->b_predecessors++; } diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index a5bc9b9b5782b2..38564d9d9b0058 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -15,7 +15,7 @@ #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_weakref.h" // _PyWeakref_ClearRef() #include "pydtrace.h" -#include "pycore_typeid.h" // _PyType_MergeThreadLocalRefcounts +#include "pycore_uniqueid.h" // _PyType_MergeThreadLocalRefcounts #ifdef Py_GIL_DISABLED @@ -217,12 +217,12 @@ disable_deferred_refcounting(PyObject *op) merge_refcount(op, 0); } - // Heap types also use thread-local refcounting -- disable it here. + // Heap types also use per-thread refcounting -- disable it here. if (PyType_Check(op)) { - // Disable thread-local refcounting for heap types - PyTypeObject *type = (PyTypeObject *)op; - if (PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) { - _PyType_ReleaseId((PyHeapTypeObject *)op); + if (PyType_HasFeature((PyTypeObject *)op, Py_TPFLAGS_HEAPTYPE)) { + PyHeapTypeObject *ht = (PyHeapTypeObject *)op; + _PyObject_ReleaseUniqueId(ht->unique_id); + ht->unique_id = -1; } } @@ -1221,7 +1221,7 @@ gc_collect_internal(PyInterpreterState *interp, struct collection_state *state, _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)p; // merge per-thread refcount for types into the type's actual refcount - _PyType_MergeThreadLocalRefcounts(tstate); + _PyObject_MergePerThreadRefcounts(tstate); // merge refcounts for all queued objects merge_queued_objects(tstate, state); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 1201fe82efb919..e1107caa197d7a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -20,15 +20,17 @@ _PyStackRef rhs; _PyStackRef res; // _SPECIALIZE_BINARY_OP - rhs = stack_pointer[-1]; - lhs = stack_pointer[-2]; { + rhs = stack_pointer[-1]; + lhs = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, LOCALS_ARRAY); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(BINARY_OP); @@ -42,7 +44,9 @@ PyObject *lhs_o = PyStackRef_AsPyObjectBorrow(lhs); PyObject *rhs_o = PyStackRef_AsPyObjectBorrow(rhs); assert(_PyEval_BinaryOps[oparg]); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_BinaryOps[oparg](lhs_o, rhs_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(lhs); PyStackRef_CLOSE(rhs); if (res_o == NULL) goto pop_2_error; @@ -63,9 +67,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_FLOAT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyFloat_CheckExact(left_o), BINARY_OP); @@ -99,9 +103,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_INT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyLong_CheckExact(left_o), BINARY_OP); @@ -134,9 +138,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_UNICODE - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyUnicode_CheckExact(left_o), BINARY_OP); @@ -168,9 +172,9 @@ _PyStackRef left; _PyStackRef right; // _GUARD_BOTH_UNICODE - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyUnicode_CheckExact(left_o), BINARY_OP); @@ -230,9 +234,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_FLOAT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyFloat_CheckExact(left_o), BINARY_OP); @@ -266,9 +270,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_INT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyLong_CheckExact(left_o), BINARY_OP); @@ -301,9 +305,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_FLOAT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyFloat_CheckExact(left_o), BINARY_OP); @@ -337,9 +341,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_INT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyLong_CheckExact(left_o), BINARY_OP); @@ -353,7 +357,7 @@ STAT_INC(BINARY_OP, hit); PyObject *res_o = _PyLong_Subtract((PyLongObject *)left_o, (PyLongObject *)right_o); _Py_DECREF_SPECIALIZED(right_o, (destructor)PyObject_Free); - _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free);; + _Py_DECREF_SPECIALIZED(left_o, (destructor)PyObject_Free); if (res_o == NULL) goto pop_2_error; res = PyStackRef_FromPyObjectSteal(res_o); } @@ -379,12 +383,14 @@ #endif /* ENABLE_SPECIALIZATION */ } // _BINARY_SLICE - stop = stack_pointer[-1]; - start = stack_pointer[-2]; - container = stack_pointer[-3]; { + stop = stack_pointer[-1]; + start = stack_pointer[-2]; + container = stack_pointer[-3]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), PyStackRef_AsPyObjectSteal(stop)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyObject *res_o; // Can't use ERROR_IF() here, because we haven't // DECREF'ed container yet, and we still own slice. @@ -392,8 +398,14 @@ res_o = NULL; } else { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); res_o = PyObject_GetItem(PyStackRef_AsPyObjectBorrow(container), slice); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(slice); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } PyStackRef_CLOSE(container); if (res_o == NULL) goto pop_3_error; @@ -416,15 +428,18 @@ _PyStackRef sub; _PyStackRef res; // _SPECIALIZE_BINARY_SUBSCR - sub = stack_pointer[-1]; - container = stack_pointer[-2]; { + sub = stack_pointer[-1]; + container = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; + assert(frame->stackpointer == NULL); #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_BinarySubscr(container, sub, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(BINARY_SUBSCR); @@ -435,7 +450,9 @@ { PyObject *container_o = PyStackRef_AsPyObjectBorrow(container); PyObject *sub_o = PyStackRef_AsPyObjectBorrow(sub); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_GetItem(container_o, sub_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(container); PyStackRef_CLOSE(sub); if (res_o == NULL) goto pop_2_error; @@ -463,9 +480,13 @@ DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR); STAT_INC(BINARY_SUBSCR, hit); PyObject *res_o; + _PyFrame_SetStackPointer(frame, stack_pointer); int rc = PyDict_GetItemRef(dict, sub, &res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (rc == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetKeyError(sub); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(dict_st); PyStackRef_CLOSE(sub_st); @@ -492,8 +513,8 @@ DEOPT_IF(tstate->interp->eval_frame, BINARY_SUBSCR); } // _BINARY_SUBSCR_CHECK_FUNC - container = stack_pointer[-2]; { + container = stack_pointer[-2]; PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container)); DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR); PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; @@ -508,14 +529,12 @@ STAT_INC(BINARY_SUBSCR, hit); } // _BINARY_SUBSCR_INIT_CALL - sub = stack_pointer[-1]; { + sub = stack_pointer[-1]; PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container)); PyHeapTypeObject *ht = (PyHeapTypeObject *)tp; PyObject *getitem = ht->_spec_cache.getitem; new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame); - stack_pointer += -2; - assert(WITHIN_STACK_BOUNDS()); new_frame->localsplus[0] = container; new_frame->localsplus[1] = sub; frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_BINARY_SUBSCR); @@ -525,10 +544,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -671,10 +693,12 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *map_o = _PyDict_FromItems( values_o, 2, values_o+1, 2, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(values_o); for (int _i = oparg*2; --_i >= 0;) { PyStackRef_CLOSE(values[_i]); @@ -698,7 +722,9 @@ _PyStackRef *values; _PyStackRef set; values = &stack_pointer[-oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *set_o = PySet_New(NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); if (set_o == NULL) { for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(values[_i]); @@ -712,7 +738,9 @@ int err = 0; for (int i = 0; i < oparg; i++) { if (err == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); err = PySet_Add(set_o, PyStackRef_AsPyObjectBorrow(values[i])); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(values[i]); } @@ -832,22 +860,24 @@ PREDICTED(CALL); _Py_CODEUNIT *this_instr = next_instr - 4; (void)this_instr; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; - _PyStackRef func; + _PyStackRef *func; _PyStackRef *maybe_self; _PyStackRef res; // _SPECIALIZE_CALL - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; - _Py_Specialize_Call(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_Call(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(CALL); @@ -856,27 +886,26 @@ } /* Skip 2 cache entries */ // _MAYBE_EXPAND_METHOD - args = &stack_pointer[-oparg]; { + args = &stack_pointer[-oparg]; + func = &stack_pointer[-2 - oparg]; maybe_self = &stack_pointer[-1 - oparg]; - if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *self = ((PyMethodObject *)callable_o)->im_self; maybe_self[0] = PyStackRef_FromPyObjectNew(self); PyObject *method = ((PyMethodObject *)callable_o)->im_func; - func = PyStackRef_FromPyObjectNew(method); - stack_pointer[-2 - oparg] = func; - PyStackRef_CLOSE(callable); - } - else { - func = callable; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); } } // _DO_CALL - self_or_null = maybe_self; - callable = func; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -890,12 +919,15 @@ { int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, total_args, NULL, frame ); + stack_pointer = _PyFrame_GetStackPointer(frame); // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { @@ -907,7 +939,7 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -917,30 +949,36 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); if (opcode == INSTRUMENTED_CALL) { PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(args[0]); if (res_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, frame, this_instr, callable_o, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, frame, this_instr, callable_o, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { Py_CLEAR(res_o); } } } assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -954,15 +992,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -976,11 +1016,11 @@ next_instr += 4; INSTRUCTION_STATS(CALL_ALLOC_AND_ENTER_INIT); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; - _PyStackRef null; + _PyStackRef *callable; + _PyStackRef *null; _PyStackRef *args; - _PyStackRef self; - _PyStackRef init; + _PyStackRef *init; + _PyStackRef *self; _PyInterpreterFrame *init_frame; _PyInterpreterFrame *new_frame; /* Skip 1 cache entry */ @@ -989,13 +1029,15 @@ DEOPT_IF(tstate->interp->eval_frame, CALL); } // _CHECK_AND_ALLOCATE_OBJECT - args = &stack_pointer[-oparg]; - null = stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + args = &stack_pointer[-oparg]; + null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + init = &stack_pointer[-2 - oparg]; + self = &stack_pointer[-1 - oparg]; uint32_t type_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); - DEOPT_IF(!PyStackRef_IsNull(null), CALL); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); + DEOPT_IF(!PyStackRef_IsNull(null[0]), CALL); DEOPT_IF(!PyType_Check(callable_o), CALL); PyTypeObject *tp = (PyTypeObject *)callable_o; DEOPT_IF(tp->tp_version_tag != type_version, CALL); @@ -1005,25 +1047,33 @@ PyCodeObject *code = (PyCodeObject *)init_func->func_code; DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize + _Py_InitCleanup.co_framesize), CALL); STAT_INC(CALL, hit); - self = PyStackRef_FromPyObjectSteal(_PyType_NewManagedObject(tp)); - if (PyStackRef_IsNull(self)) { + PyObject *self_o = _PyType_NewManagedObject(tp); + if (self_o == NULL) { goto error; } - PyStackRef_CLOSE(callable); - init = PyStackRef_FromPyObjectNew(init_func); - stack_pointer[-1 - oparg] = init; + self[0] = PyStackRef_FromPyObjectSteal(self_o); + _PyStackRef temp = callable[0]; + init[0] = PyStackRef_FromPyObjectNew(init_func); + PyStackRef_CLOSE(temp); } // _CREATE_INIT_FRAME { + args = &stack_pointer[-oparg]; + self = &stack_pointer[-1 - oparg]; + init = &stack_pointer[-2 - oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( tstate, (PyCodeObject *)&_Py_InitCleanup, 1, frame); + stack_pointer = _PyFrame_GetStackPointer(frame); assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK); /* Push self onto stack of shim */ - shim->localsplus[0] = PyStackRef_DUP(self); - args[-1] = self; + shim->localsplus[0] = PyStackRef_DUP(self[0]); + _PyFrame_SetStackPointer(frame, stack_pointer); init_frame = _PyEvalFramePushAndInit( - tstate, init, NULL, args-1, oparg+1, NULL, shim); - stack_pointer += -2 - oparg; + tstate, init[0], NULL, args-1, oparg+1, NULL, shim); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer[-2 - oparg].bits = (uintptr_t)init_frame; + stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); if (init_frame == NULL) { _PyEval_FrameClearAndPop(tstate, shim); @@ -1036,15 +1086,18 @@ tstate->py_recursion_remaining--; } // _PUSH_FRAME - new_frame = init_frame; { + new_frame = init_frame; // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -1058,9 +1111,9 @@ next_instr += 4; INSTRUCTION_STATS(CALL_BOUND_METHOD_EXACT_ARGS); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *null; - _PyStackRef func; + _PyStackRef *func; _PyStackRef *self; _PyStackRef *self_or_null; _PyStackRef *args; @@ -1071,36 +1124,37 @@ DEOPT_IF(tstate->interp->eval_frame, CALL); } // _CHECK_CALL_BOUND_METHOD_EXACT_ARGS - null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; DEOPT_IF(!PyStackRef_IsNull(null[0]), CALL); - DEOPT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type, CALL); + DEOPT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable[0])) != &PyMethod_Type, CALL); } // _INIT_CALL_BOUND_METHOD_EXACT_ARGS { + func = &stack_pointer[-2 - oparg]; self = &stack_pointer[-1 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); STAT_INC(CALL, hit); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - stack_pointer[-2 - oparg] = func; - PyStackRef_CLOSE(callable); + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + PyStackRef_CLOSE(temp); } // flush // _CHECK_FUNCTION_VERSION - callable = stack_pointer[-2 - oparg]; { + callable = &stack_pointer[-2 - oparg]; uint32_t func_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(!PyFunction_Check(callable_o), CALL); PyFunctionObject *func = (PyFunctionObject *)callable_o; DEOPT_IF(func->func_version != func_version, CALL); } // _CHECK_FUNCTION_EXACT_ARGS - self_or_null = &stack_pointer[-1 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + self_or_null = &stack_pointer[-1 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyFunction_Check(callable_o)); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; @@ -1108,18 +1162,18 @@ } // _CHECK_STACK_SPACE { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); DEOPT_IF(tstate->py_recursion_remaining <= 1, CALL); } // _INIT_CALL_PY_EXACT_ARGS - args = &stack_pointer[-oparg]; { + args = &stack_pointer[-oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -1140,12 +1194,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -1159,9 +1214,9 @@ next_instr += 4; INSTRUCTION_STATS(CALL_BOUND_METHOD_GENERAL); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *null; - _PyStackRef method; + _PyStackRef *method; _PyStackRef *self; _PyStackRef *self_or_null; _PyStackRef *args; @@ -1172,11 +1227,11 @@ DEOPT_IF(tstate->interp->eval_frame, CALL); } // _CHECK_METHOD_VERSION - null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; uint32_t func_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(Py_TYPE(callable_o) != &PyMethod_Type, CALL); PyObject *func = ((PyMethodObject *)callable_o)->im_func; DEOPT_IF(!PyFunction_Check(func), CALL); @@ -1185,23 +1240,24 @@ } // _EXPAND_METHOD { + method = &stack_pointer[-2 - oparg]; self = &stack_pointer[-1 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyStackRef_IsNull(null[0])); assert(Py_TYPE(callable_o) == &PyMethod_Type); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - stack_pointer[-2 - oparg] = method; - assert(PyStackRef_FunctionCheck(method)); - PyStackRef_CLOSE(callable); + _PyStackRef temp = callable[0]; + method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + assert(PyStackRef_FunctionCheck(method[0])); + PyStackRef_CLOSE(temp); } // flush // _PY_FRAME_GENERAL - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -1211,17 +1267,19 @@ assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); - new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyInterpreterFrame *temp = _PyEvalFramePushAndInit( + tstate, callable[0], locals, args, total_args, NULL, frame ); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. + stack_pointer = _PyFrame_GetStackPointer(frame); + // The frame has stolen all the arguments from the stack. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); - if (new_frame == NULL) { + if (temp == NULL) { goto error; } + new_frame = temp; } // _SAVE_RETURN_OFFSET { @@ -1237,10 +1295,11 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -1254,18 +1313,18 @@ next_instr += 4; INSTRUCTION_STATS(CALL_BUILTIN_CLASS); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_BUILTIN_CLASS - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -1277,7 +1336,7 @@ STAT_INC(CALL, hit); STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -1288,13 +1347,15 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = tp->tp_vectorcall((PyObject *)tp, args_o, total_args, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -1305,15 +1366,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -1327,19 +1390,19 @@ next_instr += 4; INSTRUCTION_STATS(CALL_BUILTIN_FAST); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_BUILTIN_FAST - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* Builtin METH_FASTCALL functions, without keywords */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -1352,7 +1415,7 @@ /* res = func(self, args, nargs) */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -1363,17 +1426,19 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = ((PyCFunctionFast)(void(*)(void))cfunc)( PyCFunction_GET_SELF(callable_o), args_o, total_args); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -1384,15 +1449,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -1406,19 +1473,19 @@ next_instr += 4; INSTRUCTION_STATS(CALL_BUILTIN_FAST_WITH_KEYWORDS); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_BUILTIN_FAST_WITH_KEYWORDS - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -1428,12 +1495,14 @@ DEOPT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS), CALL); STAT_INC(CALL, hit); /* res = func(self, args, nargs, kwnames) */ + _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = (PyCFunctionFastWithKeywords)(void(*)(void)) PyCFunction_GET_FUNCTION(callable_o); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -1444,14 +1513,16 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = cfunc(PyCFunction_GET_SELF(callable_o), args_o, total_args, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -1462,15 +1533,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -1484,19 +1557,19 @@ next_instr += 4; INSTRUCTION_STATS(CALL_BUILTIN_O); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_BUILTIN_O - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* Builtin METH_O functions */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -1511,11 +1584,13 @@ PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); _PyStackRef arg = args[0]; _Py_EnterRecursiveCallTstateUnchecked(tstate); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable_o), PyStackRef_AsPyObjectBorrow(arg)); + stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(arg); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -1526,15 +1601,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -1550,56 +1627,89 @@ PREDICTED(CALL_FUNCTION_EX); _Py_CODEUNIT *this_instr = next_instr - 1; (void)this_instr; + _PyStackRef func; + _PyStackRef callargs; + _PyStackRef kwargs_in = PyStackRef_NULL; + _PyStackRef tuple; + _PyStackRef kwargs_out = PyStackRef_NULL; _PyStackRef func_st; _PyStackRef callargs_st; _PyStackRef kwargs_st = PyStackRef_NULL; _PyStackRef result; - // __DO_CALL_FUNCTION_EX - if (oparg & 1) { kwargs_st = stack_pointer[-(oparg & 1)]; } - callargs_st = stack_pointer[-1 - (oparg & 1)]; - func_st = stack_pointer[-3 - (oparg & 1)]; + // _MAKE_CALLARGS_A_TUPLE { - PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st); - PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st); - // DICT_MERGE is called before this opcode if there are kwargs. - // It converts all dict subtypes in kwargs into regular dicts. - assert(kwargs == NULL || PyDict_CheckExact(kwargs)); - if (!PyTuple_CheckExact(callargs)) { - int err = check_args_iterable(tstate, func, callargs); + if (oparg & 1) { kwargs_in = stack_pointer[-(oparg & 1)]; } + callargs = stack_pointer[-1 - (oparg & 1)]; + func = stack_pointer[-3 - (oparg & 1)]; + PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs); + if (PyTuple_CheckExact(callargs_o)) { + tuple = callargs; + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { goto error; } - PyObject *tuple = PySequence_Tuple(callargs); - if (tuple == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *tuple_o = PySequence_Tuple(callargs_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (tuple_o == NULL) { goto error; } - PyStackRef_CLOSE(callargs_st); - callargs_st = PyStackRef_FromPyObjectSteal(tuple); - callargs = tuple; + PyStackRef_CLOSE(callargs); + tuple = PyStackRef_FromPyObjectSteal(tuple_o); } + kwargs_out = kwargs_in; + } + // _DO_CALL_FUNCTION_EX + { + kwargs_st = kwargs_out; + callargs_st = tuple; + func_st = func; + PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); + PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st); + PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st); + // DICT_MERGE is called before this opcode if there are kwargs. + // It converts all dict subtypes in kwargs into regular dicts. + assert(kwargs == NULL || PyDict_CheckExact(kwargs)); assert(PyTuple_CheckExact(callargs)); EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); + PyObject *result_o; + assert(!_PyErr_Occurred(tstate)); if (opcode == INSTRUMENTED_CALL_FUNCTION_EX) { PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ? PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING; + stack_pointer[-1 - (oparg & 1)] = callargs_st; + if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, func, arg); - if (err) goto error; - result = PyStackRef_FromPyObjectSteal(PyObject_Call(func, callargs, kwargs)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + goto error; + } + _PyFrame_SetStackPointer(frame, stack_pointer); + result_o = PyObject_Call(func, callargs, kwargs); + stack_pointer = _PyFrame_GetStackPointer(frame); if (!PyFunction_Check(func) && !PyMethod_Check(func)) { - if (PyStackRef_IsNull(result)) { + if (result_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, frame, this_instr, func, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, frame, this_instr, func, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { - PyStackRef_CLEAR(result); + Py_CLEAR(result_o); } } } @@ -1612,11 +1722,16 @@ Py_ssize_t nargs = PyTuple_GET_SIZE(callargs); int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func)); + stack_pointer[-1 - (oparg & 1)] = callargs_st; + if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st; + _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex( tstate, func_st, locals, nargs, callargs, kwargs, frame); - // Need to manually shrink the stack since we exit with DISPATCH_INLINED. - STACK_SHRINK(oparg + 3); + stack_pointer = _PyFrame_GetStackPointer(frame); + // Need to sync the stack since we exit with DISPATCH_INLINED. + stack_pointer += -3 - (oparg & 1); + assert(WITHIN_STACK_BOUNDS()); if (new_frame == NULL) { goto error; } @@ -1624,30 +1739,38 @@ frame->return_offset = 1; DISPATCH_INLINED(new_frame); } - result = PyStackRef_FromPyObjectSteal(PyObject_Call(func, callargs, kwargs)); + stack_pointer[-1 - (oparg & 1)] = callargs_st; + if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_st; + _PyFrame_SetStackPointer(frame, stack_pointer); + result_o = PyObject_Call(func, callargs, kwargs); + stack_pointer = _PyFrame_GetStackPointer(frame); } - PyStackRef_CLOSE(func_st); - PyStackRef_CLOSE(callargs_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_XCLOSE(kwargs_st); - assert(PyStackRef_AsPyObjectBorrow(PEEK(2 + (oparg & 1))) == NULL); - if (PyStackRef_IsNull(result)) { + stack_pointer = _PyFrame_GetStackPointer(frame); + PyStackRef_CLOSE(callargs_st); + PyStackRef_CLOSE(func_st); + if (result_o == NULL) { stack_pointer += -3 - (oparg & 1); assert(WITHIN_STACK_BOUNDS()); goto error; } + result = PyStackRef_FromPyObjectSteal(result_o); } // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-3 - (oparg & 1)] = result; + stack_pointer += -2 - (oparg & 1); + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-3 - (oparg & 1)] = result; - stack_pointer += -2 - (oparg & 1); - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 2 + (oparg & 1); + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-3 - (oparg & 1)] = result; @@ -1664,7 +1787,9 @@ _PyStackRef res; value = stack_pointer[-1]; assert(oparg <= MAX_INTRINSIC_1); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (res_o == NULL) goto pop_1_error; res = PyStackRef_FromPyObjectSteal(res_o); @@ -1684,7 +1809,9 @@ assert(oparg <= MAX_INTRINSIC_2); PyObject *value1 = PyStackRef_AsPyObjectBorrow(value1_st); PyObject *value2 = PyStackRef_AsPyObjectBorrow(value2_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value2_st); PyStackRef_CLOSE(value1_st); if (res_o == NULL) goto pop_2_error; @@ -1700,7 +1827,7 @@ next_instr += 4; INSTRUCTION_STATS(CALL_ISINSTANCE); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; @@ -1708,9 +1835,9 @@ /* Skip 2 cache entries */ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* isinstance(o, o2) */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -1722,7 +1849,9 @@ STAT_INC(CALL, hit); _PyStackRef cls_stackref = args[1]; _PyStackRef inst_stackref = args[0]; + _PyFrame_SetStackPointer(frame, stack_pointer); int retval = PyObject_IsInstance(PyStackRef_AsPyObjectBorrow(inst_stackref), PyStackRef_AsPyObjectBorrow(cls_stackref)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (retval < 0) { goto error; } @@ -1730,7 +1859,7 @@ assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(inst_stackref); PyStackRef_CLOSE(cls_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -1744,21 +1873,27 @@ PREDICTED(CALL_KW); _Py_CODEUNIT *this_instr = next_instr - 4; (void)this_instr; - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef kwnames; + _PyStackRef kwnames_in; + _PyStackRef *func; + _PyStackRef *maybe_self; + _PyStackRef kwnames_out; _PyStackRef res; // _SPECIALIZE_CALL_KW - self_or_null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; { + self_or_null = &stack_pointer[-2 - oparg]; + callable = &stack_pointer[-3 - oparg]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; - _Py_Specialize_CallKw(callable, next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_CallKw(callable[0], next_instr, oparg + !PyStackRef_IsNull(self_or_null[0])); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(CALL_KW); @@ -1766,11 +1901,30 @@ #endif /* ENABLE_SPECIALIZATION */ } /* Skip 2 cache entries */ + // _MAYBE_EXPAND_METHOD_KW + { + kwnames_in = stack_pointer[-1]; + args = &stack_pointer[-1 - oparg]; + func = &stack_pointer[-3 - oparg]; + maybe_self = &stack_pointer[-2 - oparg]; + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); + PyObject *self = ((PyMethodObject *)callable_o)->im_self; + maybe_self[0] = PyStackRef_FromPyObjectNew(self); + PyObject *method = ((PyMethodObject *)callable_o)->im_func; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); + } + kwnames_out = kwnames_in; + } // _DO_CALL_KW - kwnames = stack_pointer[-1]; - args = &stack_pointer[-1 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + kwnames = kwnames_out; + args = &stack_pointer[-1 - oparg]; + self_or_null = &stack_pointer[-2 - oparg]; + callable = &stack_pointer[-3 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); // oparg counts all of the args, but *not* self: int total_args = oparg; @@ -1778,17 +1932,6 @@ args--; total_args++; } - else if (Py_TYPE(callable_o) == &PyMethod_Type) { - args--; - total_args++; - PyObject *self = ((PyMethodObject *)callable_o)->im_self; - args[0] = PyStackRef_FromPyObjectNew(self); - PyObject *method = ((PyMethodObject *)callable_o)->im_func; - args[-1] = PyStackRef_FromPyObjectNew(method); - PyStackRef_CLOSE(callable); - callable_o = method; - callable = args[-1]; - } int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); // Check if the call can be inlined or not if (Py_TYPE(callable_o) == &PyFunction_Type && @@ -1797,13 +1940,17 @@ { int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); + stack_pointer[-1] = kwnames; + _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, positional_args, kwnames_o, frame ); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(kwnames); - // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 3); + // Sync stack explicitly since we leave using DISPATCH_INLINED(). + stack_pointer += -3 - oparg; + assert(WITHIN_STACK_BOUNDS()); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { @@ -1816,7 +1963,7 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -1828,23 +1975,30 @@ goto error; } } + stack_pointer[-1] = kwnames; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames_o); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); if (opcode == INSTRUMENTED_CALL_KW) { PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(args[0]); if (res_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, frame, this_instr, callable_o, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, frame, this_instr, callable_o, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { Py_CLEAR(res_o); } @@ -1852,7 +2006,7 @@ } PyStackRef_CLOSE(kwnames); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -1874,10 +2028,10 @@ next_instr += 4; INSTRUCTION_STATS(CALL_KW_BOUND_METHOD); static_assert(INLINE_CACHE_ENTRIES_CALL_KW == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *null; _PyStackRef kwnames; - _PyStackRef method; + _PyStackRef *method; _PyStackRef *self; _PyStackRef *self_or_null; _PyStackRef *args; @@ -1888,11 +2042,11 @@ DEOPT_IF(tstate->interp->eval_frame, CALL_KW); } // _CHECK_METHOD_VERSION_KW - null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; { + null = &stack_pointer[-2 - oparg]; + callable = &stack_pointer[-3 - oparg]; uint32_t func_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(Py_TYPE(callable_o) != &PyMethod_Type, CALL_KW); PyObject *func = ((PyMethodObject *)callable_o)->im_func; DEOPT_IF(!PyFunction_Check(func), CALL_KW); @@ -1900,26 +2054,26 @@ DEOPT_IF(!PyStackRef_IsNull(null[0]), CALL_KW); } // _EXPAND_METHOD_KW - kwnames = stack_pointer[-1]; { + method = &stack_pointer[-3 - oparg]; self = &stack_pointer[-2 - oparg]; - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + _PyStackRef callable_s = callable[0]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable_s); assert(PyStackRef_IsNull(null[0])); assert(Py_TYPE(callable_o) == &PyMethod_Type); self[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); - method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); - stack_pointer[-3 - oparg] = method; - assert(PyStackRef_FunctionCheck(method)); - PyStackRef_CLOSE(callable); + method[0] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); + assert(PyStackRef_FunctionCheck(method[0])); + PyStackRef_CLOSE(callable_s); } // flush // _PY_FRAME_KW - kwnames = stack_pointer[-1]; - args = &stack_pointer[-1 - oparg]; - self_or_null = &stack_pointer[-2 - oparg]; - callable = stack_pointer[-3 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + kwnames = stack_pointer[-1]; + args = &stack_pointer[-1 - oparg]; + self_or_null = &stack_pointer[-2 - oparg]; + callable = &stack_pointer[-3 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -1931,14 +2085,17 @@ assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, positional_args, kwnames_o, frame ); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(kwnames); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. - stack_pointer += -3 - oparg; + stack_pointer[-3 - oparg].bits = (uintptr_t)new_frame; + stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (new_frame == NULL) { goto error; @@ -1958,10 +2115,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -1975,7 +2135,7 @@ next_instr += 4; INSTRUCTION_STATS(CALL_KW_NON_PY); static_assert(INLINE_CACHE_ENTRIES_CALL_KW == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef kwnames; _PyStackRef *self_or_null; _PyStackRef *args; @@ -1983,21 +2143,21 @@ /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CHECK_IS_NOT_PY_CALLABLE_KW - callable = stack_pointer[-3 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-3 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(PyFunction_Check(callable_o), CALL_KW); DEOPT_IF(Py_TYPE(callable_o) == &PyMethod_Type, CALL_KW); } // _CALL_KW_NON_PY - kwnames = stack_pointer[-1]; - args = &stack_pointer[-1 - oparg]; - self_or_null = &stack_pointer[-2 - oparg]; { + kwnames = stack_pointer[-1]; + args = &stack_pointer[-1 - oparg]; + self_or_null = &stack_pointer[-2 - oparg]; #if TIER_ONE assert(opcode != INSTRUMENTED_CALL); #endif - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2006,7 +2166,7 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -2020,17 +2180,19 @@ } PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET, kwnames_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(kwnames); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -3 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -2041,15 +2203,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-3 - oparg] = res; + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-3 - oparg] = res; - stack_pointer += -2 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 2 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-3 - oparg] = res; @@ -2063,7 +2227,7 @@ next_instr += 4; INSTRUCTION_STATS(CALL_KW_PY); static_assert(INLINE_CACHE_ENTRIES_CALL_KW == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef kwnames; _PyStackRef *args; @@ -2074,20 +2238,20 @@ DEOPT_IF(tstate->interp->eval_frame, CALL_KW); } // _CHECK_FUNCTION_VERSION_KW - callable = stack_pointer[-3 - oparg]; { + callable = &stack_pointer[-3 - oparg]; uint32_t func_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(!PyFunction_Check(callable_o), CALL_KW); PyFunctionObject *func = (PyFunctionObject *)callable_o; DEOPT_IF(func->func_version != func_version, CALL_KW); } // _PY_FRAME_KW - kwnames = stack_pointer[-1]; - args = &stack_pointer[-1 - oparg]; - self_or_null = &stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + kwnames = stack_pointer[-1]; + args = &stack_pointer[-1 - oparg]; + self_or_null = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -2099,14 +2263,17 @@ assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, positional_args, kwnames_o, frame ); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(kwnames); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. - stack_pointer += -3 - oparg; + stack_pointer[-3 - oparg].bits = (uintptr_t)new_frame; + stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (new_frame == NULL) { goto error; @@ -2126,10 +2293,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -2143,7 +2313,7 @@ next_instr += 4; INSTRUCTION_STATS(CALL_LEN); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; @@ -2151,9 +2321,9 @@ /* Skip 2 cache entries */ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; + callable = &stack_pointer[-2 - oparg]; /* len(o) */ - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2165,7 +2335,9 @@ STAT_INC(CALL, hit); _PyStackRef arg_stackref = args[0]; PyObject *arg = PyStackRef_AsPyObjectBorrow(arg_stackref); + _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (len_i < 0) { goto error; } @@ -2174,7 +2346,7 @@ if (res_o == NULL) { GOTO_ERROR(error); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(arg_stackref); res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[-2 - oparg] = res; @@ -2224,18 +2396,18 @@ next_instr += 4; INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_METHOD_DESCRIPTOR_FAST - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2249,12 +2421,10 @@ PyObject *self = PyStackRef_AsPyObjectBorrow(args[0]); DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL); STAT_INC(CALL, hit); - PyCFunctionFast cfunc = - (PyCFunctionFast)(void(*)(void))meth->ml_meth; int nargs = total_args - 1; STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -2265,14 +2435,18 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFast cfunc = + (PyCFunctionFast)(void(*)(void))meth->ml_meth; PyObject *res_o = cfunc(self, (args_o + 1), nargs); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Clear the stack of the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -2283,15 +2457,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -2305,18 +2481,18 @@ next_instr += 4; INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2331,11 +2507,9 @@ DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL); STAT_INC(CALL, hit); int nargs = total_args - 1; - PyCFunctionFastWithKeywords cfunc = - (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -2346,14 +2520,18 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyCFunctionFastWithKeywords cfunc = + (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth; PyObject *res_o = cfunc(self, (args_o + 1), nargs, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); /* Free the arguments. */ for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -2364,15 +2542,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -2386,19 +2566,19 @@ next_instr += 4; INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_NOARGS); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_METHOD_DESCRIPTOR_NOARGS - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; assert(oparg == 0 || oparg == 1); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2417,11 +2597,13 @@ STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; _Py_EnterRecursiveCallTstateUnchecked(tstate); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, self, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(self_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -2432,15 +2614,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -2454,18 +2638,18 @@ next_instr += 4; INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_O); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_METHOD_DESCRIPTOR_O - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2485,14 +2669,16 @@ STAT_INC(CALL, hit); PyCFunction cfunc = meth->ml_meth; _Py_EnterRecursiveCallTstateUnchecked(tstate); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyCFunction_TrampolineCall(cfunc, PyStackRef_AsPyObjectBorrow(self_stackref), PyStackRef_AsPyObjectBorrow(arg_stackref)); + stack_pointer = _PyFrame_GetStackPointer(frame); _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); PyStackRef_CLOSE(self_stackref); PyStackRef_CLOSE(arg_stackref); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); if (res_o == NULL) { stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); @@ -2503,15 +2689,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -2525,27 +2713,27 @@ next_instr += 4; INSTRUCTION_STATS(CALL_NON_PY_GENERAL); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyStackRef res; /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CHECK_IS_NOT_PY_CALLABLE - callable = stack_pointer[-2 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + callable = &stack_pointer[-2 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(PyFunction_Check(callable_o), CALL); DEOPT_IF(Py_TYPE(callable_o) == &PyMethod_Type, CALL); } // _CALL_NON_PY_GENERAL - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; { + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; #if TIER_ONE assert(opcode != INSTRUMENTED_CALL); #endif - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -2554,7 +2742,7 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); PyStackRef_CLOSE(self_or_null[0]); for (int _i = oparg; --_i >= 0;) { PyStackRef_CLOSE(args[_i]); @@ -2565,13 +2753,15 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -2585,15 +2775,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -2607,7 +2799,7 @@ next_instr += 4; INSTRUCTION_STATS(CALL_PY_EXACT_ARGS); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyInterpreterFrame *new_frame; @@ -2617,18 +2809,18 @@ DEOPT_IF(tstate->interp->eval_frame, CALL); } // _CHECK_FUNCTION_VERSION - callable = stack_pointer[-2 - oparg]; { + callable = &stack_pointer[-2 - oparg]; uint32_t func_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(!PyFunction_Check(callable_o), CALL); PyFunctionObject *func = (PyFunctionObject *)callable_o; DEOPT_IF(func->func_version != func_version, CALL); } // _CHECK_FUNCTION_EXACT_ARGS - self_or_null = &stack_pointer[-1 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + self_or_null = &stack_pointer[-1 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); assert(PyFunction_Check(callable_o)); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; @@ -2636,18 +2828,18 @@ } // _CHECK_STACK_SPACE { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyFunctionObject *func = (PyFunctionObject *)callable_o; PyCodeObject *code = (PyCodeObject *)func->func_code; DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL); DEOPT_IF(tstate->py_recursion_remaining <= 1, CALL); } // _INIT_CALL_PY_EXACT_ARGS - args = &stack_pointer[-oparg]; { + args = &stack_pointer[-oparg]; int has_self = !PyStackRef_IsNull(self_or_null[0]); STAT_INC(CALL, hit); - new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame); + new_frame = _PyFrame_PushUnchecked(tstate, callable[0], oparg + has_self, frame); _PyStackRef *first_non_self_local = new_frame->localsplus + has_self; new_frame->localsplus[0] = self_or_null[0]; for (int i = 0; i < oparg; i++) { @@ -2668,12 +2860,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -2687,7 +2880,7 @@ next_instr += 4; INSTRUCTION_STATS(CALL_PY_GENERAL); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; _PyInterpreterFrame *new_frame; @@ -2697,19 +2890,19 @@ DEOPT_IF(tstate->interp->eval_frame, CALL); } // _CHECK_FUNCTION_VERSION - callable = stack_pointer[-2 - oparg]; { + callable = &stack_pointer[-2 - oparg]; uint32_t func_version = read_u32(&this_instr[2].cache); - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); DEOPT_IF(!PyFunction_Check(callable_o), CALL); PyFunctionObject *func = (PyFunctionObject *)callable_o; DEOPT_IF(func->func_version != func_version, CALL); } // _PY_FRAME_GENERAL - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -2719,17 +2912,19 @@ assert(Py_TYPE(callable_o) == &PyFunction_Type); int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); - new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyInterpreterFrame *temp = _PyEvalFramePushAndInit( + tstate, callable[0], locals, args, total_args, NULL, frame ); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. + stack_pointer = _PyFrame_GetStackPointer(frame); + // The frame has stolen all the arguments from the stack. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); - if (new_frame == NULL) { + if (temp == NULL) { goto error; } + new_frame = temp; } // _SAVE_RETURN_OFFSET { @@ -2745,10 +2940,11 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -2769,27 +2965,36 @@ /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_STR_1 - arg = stack_pointer[-1]; - null = stack_pointer[-2]; - callable = stack_pointer[-3]; { + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg); assert(oparg == 1); DEOPT_IF(!PyStackRef_IsNull(null), CALL); DEOPT_IF(callable_o != (PyObject *)&PyUnicode_Type, CALL); STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); res = PyStackRef_FromPyObjectSteal(PyObject_Str(arg_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(arg); if (PyStackRef_IsNull(res)) goto pop_3_error; } // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-3] = res; + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) goto pop_2_error; + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-3] = res; @@ -2810,27 +3015,36 @@ /* Skip 1 cache entry */ /* Skip 2 cache entries */ // _CALL_TUPLE_1 - arg = stack_pointer[-1]; - null = stack_pointer[-2]; - callable = stack_pointer[-3]; { + arg = stack_pointer[-1]; + null = stack_pointer[-2]; + callable = stack_pointer[-3]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *arg_o = PyStackRef_AsPyObjectBorrow(arg); assert(oparg == 1); DEOPT_IF(!PyStackRef_IsNull(null), CALL); DEOPT_IF(callable_o != (PyObject *)&PyTuple_Type, CALL); STAT_INC(CALL, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); res = PyStackRef_FromPyObjectSteal(PySequence_Tuple(arg_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(arg); if (PyStackRef_IsNull(res)) goto pop_3_error; } // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-3] = res; + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) goto pop_2_error; + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-3] = res; @@ -2879,7 +3093,9 @@ exc_value_st = stack_pointer[-2]; PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); PyObject *match_type = PyStackRef_AsPyObjectBorrow(match_type_st); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyEval_CheckExceptStarTypeValid(tstate, match_type); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { PyStackRef_CLOSE(exc_value_st); PyStackRef_CLOSE(match_type_st); @@ -2887,15 +3103,23 @@ } PyObject *match_o = NULL; PyObject *rest_o = NULL; + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_ExceptionGroupMatch(exc_value, match_type, &match_o, &rest_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(exc_value_st); PyStackRef_CLOSE(match_type_st); if (res < 0) goto pop_2_error; assert((match_o == NULL) == (rest_o == NULL)); if (match_o == NULL) goto pop_2_error; if (!Py_IsNone(match_o)) { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); PyErr_SetHandledException(match_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } rest = PyStackRef_FromPyObjectSteal(rest_o); match = PyStackRef_FromPyObjectSteal(match_o); @@ -2916,12 +3140,16 @@ PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); assert(PyExceptionInstance_Check(left_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyEval_CheckExceptTypeValid(tstate, right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { PyStackRef_CLOSE(right); if (true) goto pop_1_error; } + _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyErr_GivenExceptionMatches(left_o, right_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(right); b = res ? PyStackRef_True : PyStackRef_False; stack_pointer[-1] = b; @@ -2944,21 +3172,25 @@ PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st); assert(throwflag); assert(exc_value && PyExceptionInstance_Check(exc_value)); + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { + none = PyStackRef_None; value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value); - stack_pointer[-2] = value; PyStackRef_CLOSE(sub_iter_st); PyStackRef_CLOSE(last_sent_val_st); PyStackRef_CLOSE(exc_value_st); - none = PyStackRef_None; } else { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetRaisedException(tstate, Py_NewRef(exc_value)); monitor_reraise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); goto exception_unwind; } stack_pointer[-3] = none; + stack_pointer[-2] = value; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -2975,15 +3207,17 @@ _PyStackRef right; _PyStackRef res; // _SPECIALIZE_COMPARE_OP - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_CompareOp(left, right, next_instr, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(COMPARE_OP); @@ -2995,22 +3229,30 @@ PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); assert((oparg >> 5) <= Py_GE); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_RichCompare(left_o, right_o, oparg >> 5); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res_o == NULL) goto pop_2_error; if (oparg & 16) { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int res_bool = PyObject_IsTrue(res_o); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(res_o); - if (res_bool < 0) goto pop_2_error; + if (res_bool < 0) goto error; res = res_bool ? PyStackRef_True : PyStackRef_False; } else { res = PyStackRef_FromPyObjectSteal(res_o); + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); } } - stack_pointer[-2] = res; - stack_pointer += -1; + stack_pointer[0] = res; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -3024,9 +3266,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_FLOAT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyFloat_CheckExact(left_o), COMPARE_OP); @@ -3062,9 +3304,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_INT - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyLong_CheckExact(left_o), COMPARE_OP); @@ -3104,9 +3346,9 @@ _PyStackRef right; _PyStackRef res; // _GUARD_BOTH_UNICODE - right = stack_pointer[-1]; - left = stack_pointer[-2]; { + right = stack_pointer[-1]; + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyUnicode_CheckExact(left_o), COMPARE_OP); @@ -3145,14 +3387,16 @@ _PyStackRef right; _PyStackRef b; // _SPECIALIZE_CONTAINS_OP - right = stack_pointer[-1]; { + right = stack_pointer[-1]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_ContainsOp(right, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(CONTAINS_OP); @@ -3160,11 +3404,13 @@ #endif /* ENABLE_SPECIALIZATION */ } // _CONTAINS_OP - left = stack_pointer[-2]; { + left = stack_pointer[-2]; PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); + _PyFrame_SetStackPointer(frame, stack_pointer); int res = PySequence_Contains(right_o, left_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res < 0) goto pop_2_error; @@ -3191,7 +3437,9 @@ PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); DEOPT_IF(!PyDict_CheckExact(right_o), CONTAINS_OP); STAT_INC(CONTAINS_OP, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); int res = PyDict_Contains(right_o, left_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res < 0) goto pop_2_error; @@ -3218,7 +3466,9 @@ DEOPT_IF(!(PySet_CheckExact(right_o) || PyFrozenSet_CheckExact(right_o)), CONTAINS_OP); STAT_INC(CONTAINS_OP, hit); // Note: both set and frozenset use the same seq_contains method! + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PySet_Contains((PySetObject *)right_o, left_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(left); PyStackRef_CLOSE(right); if (res < 0) goto pop_2_error; @@ -3239,7 +3489,9 @@ conversion_func conv_fn; assert(oparg >= FVC_STR && oparg <= FVC_ASCII); conv_fn = _PyEval_ConversionFuncs[oparg]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *result_o = conv_fn(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (result_o == NULL) goto pop_1_error; result = PyStackRef_FromPyObjectSteal(result_o); @@ -3287,7 +3539,9 @@ _PyStackRef owner; owner = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelAttr(PyStackRef_AsPyObjectBorrow(owner), name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(owner); if (err) goto pop_1_error; stack_pointer += -1; @@ -3304,7 +3558,9 @@ // Fortunately we don't need its superpower. PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL); if (oldobj == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } Py_DECREF(oldobj); @@ -3317,10 +3573,12 @@ INSTRUCTION_STATS(DELETE_FAST); _PyStackRef v = GETLOCAL(oparg); if (PyStackRef_IsNull(v)) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (1) goto error; } SETLOCAL(oparg, PyStackRef_NULL); @@ -3332,14 +3590,18 @@ next_instr += 1; INSTRUCTION_STATS(DELETE_GLOBAL); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_Pop(GLOBALS(), name, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); // Can't use ERROR_IF here. if (err < 0) { goto error; } if (err == 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } DISPATCH(); @@ -3353,16 +3615,22 @@ PyObject *ns = LOCALS(); int err; if (ns == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_SystemError, "no locals when deleting %R", name); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } + _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_DelItem(ns, name); + stack_pointer = _PyFrame_GetStackPointer(frame); // Can't use ERROR_IF here. if (err != 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } DISPATCH(); @@ -3377,8 +3645,10 @@ sub = stack_pointer[-1]; container = stack_pointer[-2]; /* del container[sub] */ + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(container); PyStackRef_CLOSE(sub); if (err) goto pop_2_error; @@ -3400,9 +3670,13 @@ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_MergeEx(dict_o, update_o, 2); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatKwargsError(tstate, callable_o, update_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(update); if (true) goto pop_1_error; } @@ -3422,13 +3696,19 @@ dict = stack_pointer[-2 - (oparg - 1)]; PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *update_o = PyStackRef_AsPyObjectBorrow(update); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_Update(dict_o, update_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_AttributeError); + stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'%.200s' object is not a mapping", Py_TYPE(update_o)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(update); if (true) goto pop_1_error; @@ -3450,14 +3730,19 @@ awaitable_st = stack_pointer[-2]; PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); assert(exc && PyExceptionInstance_Check(exc)); - if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + int matches = PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (matches) { PyStackRef_CLOSE(awaitable_st); PyStackRef_CLOSE(exc_st); } else { Py_INCREF(exc); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetRaisedException(tstate, exc); monitor_reraise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); goto exception_unwind; } stack_pointer += -2; @@ -3483,11 +3768,13 @@ INSTRUCTION_STATS(END_SEND); _PyStackRef receiver; _PyStackRef value; + _PyStackRef val; value = stack_pointer[-1]; receiver = stack_pointer[-2]; (void)receiver; + val = value; PyStackRef_CLOSE(receiver); - stack_pointer[-2] = value; + stack_pointer[-2] = val; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -3534,9 +3821,11 @@ should_be_none = stack_pointer[-1]; assert(STACK_LEVEL() == 2); if (!PyStackRef_Is(should_be_none, PyStackRef_None)) { + _PyFrame_SetStackPointer(frame, stack_pointer); PyErr_Format(PyExc_TypeError, "__init__() should return None, not '%.200s'", Py_TYPE(PyStackRef_AsPyObjectBorrow(should_be_none))->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } stack_pointer += -1; @@ -3566,9 +3855,12 @@ /* If value is a unicode object, then we know the result * of format(value) is value itself. */ if (!PyUnicode_CheckExact(value_o)) { - res = PyStackRef_FromPyObjectSteal(PyObject_Format(value_o, NULL)); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = PyObject_Format(value_o, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); - if (PyStackRef_IsNull(res)) goto pop_1_error; + if (res_o == NULL) goto pop_1_error; + res = PyStackRef_FromPyObjectSteal(res_o); } else { res = value; @@ -3586,7 +3878,9 @@ _PyStackRef res; fmt_spec = stack_pointer[-1]; value = stack_pointer[-2]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Format(PyStackRef_AsPyObjectBorrow(value), PyStackRef_AsPyObjectBorrow(fmt_spec)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); PyStackRef_CLOSE(fmt_spec); if (res_o == NULL) goto pop_2_error; @@ -3607,14 +3901,16 @@ _PyStackRef iter; _PyStackRef next; // _SPECIALIZE_FOR_ITER - iter = stack_pointer[-1]; { + iter = stack_pointer[-1]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_ForIter(iter, next_instr, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(FOR_ITER); @@ -3625,16 +3921,21 @@ { /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (next_o == NULL) { - next = PyStackRef_NULL; if (_PyErr_Occurred(tstate)) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); if (!matches) { goto error; } + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_MonitorRaise(tstate, frame, this_instr); _PyErr_Clear(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); } /* iterator ended normally */ assert(next_instr[oparg].op.code == END_FOR || @@ -3668,8 +3969,8 @@ DEOPT_IF(tstate->interp->eval_frame, FOR_ITER); } // _FOR_ITER_GEN_FRAME - iter = stack_pointer[-1]; { + iter = stack_pointer[-1]; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); DEOPT_IF(Py_TYPE(gen) != &PyGen_Type, FOR_ITER); DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, FOR_ITER); @@ -3684,15 +3985,16 @@ frame->return_offset = (uint16_t)(1 + INLINE_CACHE_ENTRIES_FOR_ITER + oparg); } // _PUSH_FRAME - new_frame = gen_frame; { + new_frame = gen_frame; // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -3710,8 +4012,8 @@ _PyStackRef next; /* Skip 1 cache entry */ // _ITER_CHECK_LIST - iter = stack_pointer[-1]; { + iter = stack_pointer[-1]; DEOPT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(iter)) != &PyListIter_Type, FOR_ITER); } // _ITER_JUMP_LIST @@ -3745,8 +4047,8 @@ assert(seq); assert(it->it_index < PyList_GET_SIZE(seq)); next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++)); - stack_pointer[0] = next; } + stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -3761,8 +4063,8 @@ _PyStackRef next; /* Skip 1 cache entry */ // _ITER_CHECK_RANGE - iter = stack_pointer[-1]; { + iter = stack_pointer[-1]; _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, FOR_ITER); } @@ -3806,8 +4108,8 @@ _PyStackRef next; /* Skip 1 cache entry */ // _ITER_CHECK_TUPLE - iter = stack_pointer[-1]; { + iter = stack_pointer[-1]; DEOPT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(iter)) != &PyTupleIter_Type, FOR_ITER); } // _ITER_JUMP_TUPLE @@ -3838,8 +4140,8 @@ assert(seq); assert(it->it_index < PyTuple_GET_SIZE(seq)); next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, it->it_index++)); - stack_pointer[0] = next; } + stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -3860,24 +4162,32 @@ getter = type->tp_as_async->am_aiter; } if (getter == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'async for' requires an object with " "__aiter__ method, got %.100s", type->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(obj); if (true) goto pop_1_error; } + _PyFrame_SetStackPointer(frame, stack_pointer); iter_o = (*getter)(obj_o); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(obj); if (iter_o == NULL) goto pop_1_error; if (Py_TYPE(iter_o)->tp_as_async == NULL || Py_TYPE(iter_o)->tp_as_async->am_anext == NULL) { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, "'async for' received an object from __aiter__ " "that does not implement __anext__: %.100s", Py_TYPE(iter_o)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(iter_o); - if (true) goto pop_1_error; + if (true) goto error; } iter = PyStackRef_FromPyObjectSteal(iter_o); stack_pointer[-1] = iter; @@ -3891,7 +4201,9 @@ _PyStackRef aiter; _PyStackRef awaitable; aiter = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *awaitable_o = _PyEval_GetANext(PyStackRef_AsPyObjectBorrow(aiter)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (awaitable_o == NULL) { goto error; } @@ -3909,7 +4221,9 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(iterable); if (iter_o == NULL) goto pop_1_error; iter = PyStackRef_FromPyObjectSteal(iter_o); @@ -3925,9 +4239,12 @@ _PyStackRef iter; iterable = stack_pointer[-1]; /* before: [obj]; after [getiter(obj)] */ - iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable))); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(iterable); - if (PyStackRef_IsNull(iter)) goto pop_1_error; + if (iter_o == NULL) goto pop_1_error; + iter = PyStackRef_FromPyObjectSteal(iter_o); stack_pointer[-1] = iter; DISPATCH(); } @@ -3940,7 +4257,9 @@ _PyStackRef len; obj = stack_pointer[-1]; // PUSH(len(TOS)) + _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(PyStackRef_AsPyObjectBorrow(obj)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (len_i < 0) goto error; PyObject *len_o = PyLong_FromSsize_t(len_i); if (len_o == NULL) goto error; @@ -3965,23 +4284,29 @@ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } iter = iterable; } - else if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } else { - /* `iterable` is not a generator. */ - iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o)); - if (PyStackRef_IsNull(iter)) { - goto error; + if (PyGen_CheckExact(iterable_o)) { + iter = iterable; + } + else { + /* `iterable` is not a generator. */ + _PyFrame_SetStackPointer(frame, stack_pointer); + iter = PyStackRef_FromPyObjectSteal(PyObject_GetIter(iterable_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (PyStackRef_IsNull(iter)) { + goto error; + } + PyStackRef_CLOSE(iterable); } - PyStackRef_CLOSE(iterable); } stack_pointer[-1] = iter; DISPATCH(); @@ -3995,7 +4320,9 @@ _PyStackRef res; from = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); + stack_pointer = _PyFrame_GetStackPointer(frame); if (res_o == NULL) goto error; res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; @@ -4014,9 +4341,11 @@ fromlist = stack_pointer[-1]; level = stack_pointer[-2]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = _PyEval_ImportName(tstate, frame, name, PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(level); PyStackRef_CLOSE(fromlist); if (res_o == NULL) goto pop_2_error; @@ -4032,57 +4361,62 @@ (void)this_instr; next_instr += 4; INSTRUCTION_STATS(INSTRUMENTED_CALL); - _PyStackRef callable; + _PyStackRef *callable; _PyStackRef *self_or_null; _PyStackRef *args; - _PyStackRef func; + _PyStackRef *func; _PyStackRef *maybe_self; _PyStackRef res; /* Skip 3 cache entries */ // _MAYBE_EXPAND_METHOD - args = &stack_pointer[-oparg]; - self_or_null = &stack_pointer[-1 - oparg]; - callable = stack_pointer[-2 - oparg]; { + args = &stack_pointer[-oparg]; + self_or_null = &stack_pointer[-1 - oparg]; + callable = &stack_pointer[-2 - oparg]; + func = &stack_pointer[-2 - oparg]; maybe_self = &stack_pointer[-1 - oparg]; - if (PyStackRef_TYPE(callable) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) { + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *self = ((PyMethodObject *)callable_o)->im_self; maybe_self[0] = PyStackRef_FromPyObjectNew(self); PyObject *method = ((PyMethodObject *)callable_o)->im_func; - func = PyStackRef_FromPyObjectNew(method); - stack_pointer[-2 - oparg] = func; - PyStackRef_CLOSE(callable); - } - else { - func = callable; + _PyStackRef temp = callable[0]; + func[0] = PyStackRef_FromPyObjectNew(method); + PyStackRef_CLOSE(temp); } } // _MONITOR_CALL { + args = &stack_pointer[-oparg]; + maybe_self = &stack_pointer[-1 - oparg]; + func = &stack_pointer[-2 - oparg]; int is_meth = !PyStackRef_IsNull(maybe_self[0]); - PyObject *function = PyStackRef_AsPyObjectBorrow(func); + PyObject *function = PyStackRef_AsPyObjectBorrow(func[0]); PyObject *arg0; if (is_meth) { arg0 = PyStackRef_AsPyObjectBorrow(maybe_self[0]); } - else if (oparg) { - arg0 = PyStackRef_AsPyObjectBorrow(args[0]); - } else { - arg0 = &_PyInstrumentation_MISSING; + if (oparg) { + arg0 = PyStackRef_AsPyObjectBorrow(args[0]); + } + else { + arg0 = &_PyInstrumentation_MISSING; + } } + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, function, arg0 ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) goto error; } // _DO_CALL - self_or_null = maybe_self; - callable = func; { - PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); + self_or_null = maybe_self; + callable = func; + PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -4096,12 +4430,15 @@ { int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o)); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( - tstate, callable, locals, + tstate, callable[0], locals, args, total_args, NULL, frame ); + stack_pointer = _PyFrame_GetStackPointer(frame); // Manipulate stack directly since we leave using DISPATCH_INLINED(). - STACK_SHRINK(oparg + 2); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { @@ -4113,7 +4450,7 @@ /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(args, total_args, args_o); if (CONVERSION_FAILED(args_o)) { - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -4123,30 +4460,36 @@ goto error; } } + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, total_args | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); if (opcode == INSTRUMENTED_CALL) { PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(args[0]); if (res_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, frame, this_instr, callable_o, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, frame, this_instr, callable_o, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { Py_CLEAR(res_o); } } } assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); - PyStackRef_CLOSE(callable); + PyStackRef_CLOSE(callable[0]); for (int i = 0; i < total_args; i++) { PyStackRef_CLOSE(args[i]); } @@ -4160,15 +4503,17 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + stack_pointer[-2 - oparg] = res; + stack_pointer += -1 - oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); - if (err != 0) { - stack_pointer[-2 - oparg] = res; - stack_pointer += -1 - oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err != 0) goto error; + stack_pointer += 1 + oparg; + assert(WITHIN_STACK_BOUNDS()); } } stack_pointer[-2 - oparg] = res; @@ -4198,9 +4543,11 @@ PyObject *function = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 3)); PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(PEEK(total_args + 1)); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, function, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) goto error; PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); GO_TO_INSTRUCTION(CALL_KW); @@ -4218,7 +4565,9 @@ /* Need to create a fake StopIteration error here, * to conform to PEP 380 */ if (PyStackRef_GenCheck(receiver)) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { goto error; } @@ -4236,17 +4585,21 @@ INSTRUCTION_STATS(INSTRUMENTED_END_SEND); _PyStackRef receiver; _PyStackRef value; + _PyStackRef val; value = stack_pointer[-1]; receiver = stack_pointer[-2]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); if (PyGen_Check(receiver_o) || PyCoro_CheckExact(receiver_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { goto error; } } + val = value; PyStackRef_CLOSE(receiver); - stack_pointer[-2] = value; + stack_pointer[-2] = val; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -4261,19 +4614,25 @@ _Py_CODEUNIT *target; _PyStackRef iter_stackref = TOP(); PyObject *iter = PyStackRef_AsPyObjectBorrow(iter_stackref); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); + stack_pointer = _PyFrame_GetStackPointer(frame); if (next != NULL) { PUSH(PyStackRef_FromPyObjectSteal(next)); target = next_instr; } else { if (_PyErr_Occurred(tstate)) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); if (!matches) { goto error; } + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_MonitorRaise(tstate, frame, this_instr); _PyErr_Clear(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); } /* iterator ended normally */ assert(next_instr[oparg].op.code == END_FOR || @@ -4292,8 +4651,10 @@ (void)this_instr; next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_INSTRUCTION); + _PyFrame_SetStackPointer(frame, stack_pointer); int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); if (next_opcode < 0) goto error; next_instr = this_instr; if (_PyOpcode_Caches[next_opcode]) { @@ -4313,9 +4674,11 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) goto error; } } @@ -4380,6 +4743,8 @@ // don't want to specialize instrumented instructions PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); } TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { @@ -4473,7 +4838,9 @@ uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK; uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); if (code_version != global_version) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { goto error; } @@ -4488,7 +4855,9 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); \ if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) goto error; } } @@ -4520,22 +4889,29 @@ // _LOAD_CONST { value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg)); - stack_pointer[0] = value; } // _RETURN_VALUE_EVENT - val = value; { + val = value; + stack_pointer[0] = val; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, this_instr, PyStackRef_AsPyObjectBorrow(val)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) goto error; } // _RETURN_VALUE - retval = val; { + retval = val; #if TIER_ONE assert(frame != &entry_frame); #endif + _PyStackRef temp = retval; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(EMPTY()); _Py_LeaveRecursiveCallPy(tstate); @@ -4543,9 +4919,9 @@ _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(frame->return_offset); - res = retval; + res = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = res; @@ -4563,19 +4939,22 @@ _PyStackRef retval; _PyStackRef res; // _RETURN_VALUE_EVENT - val = stack_pointer[-1]; { + val = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, this_instr, PyStackRef_AsPyObjectBorrow(val)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) goto error; } // _RETURN_VALUE - retval = val; { + retval = val; #if TIER_ONE assert(frame != &entry_frame); #endif + _PyStackRef temp = retval; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4585,9 +4964,9 @@ _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(frame->return_offset); - res = retval; + res = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = res; @@ -4605,22 +4984,24 @@ _PyStackRef retval; _PyStackRef value; // _YIELD_VALUE_EVENT - val = stack_pointer[-1]; { - SAVE_SP(); + val = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_YIELD, frame, this_instr, PyStackRef_AsPyObjectBorrow(val)); - LOAD_SP(); - if (err) goto error; + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + goto error; + } if (frame->instr_ptr != this_instr) { next_instr = frame->instr_ptr; DISPATCH(); } } // _YIELD_VALUE - retval = val; { + retval = val; // NOTE: It's important that YIELD_VALUE never raises an exception! // The compiler treats any exception raised here as a failed close() // or throw() call. @@ -4632,6 +5013,7 @@ assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); assert(oparg == 0 || oparg == 1); gen->gi_frame_state = FRAME_SUSPENDED + oparg; + _PyStackRef temp = retval; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4645,15 +5027,15 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || - frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); + frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); #endif + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - LOAD_SP(); - value = retval; + value = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = value; @@ -4675,6 +5057,8 @@ assert(!_PyErr_Occurred(tstate)); tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS; return PyStackRef_AsPyObjectSteal(retval); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); } TARGET(IS_OP) { @@ -4710,9 +5094,11 @@ // _CHECK_PERIODIC { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) goto error; } } @@ -4733,7 +5119,9 @@ start--; } _PyExecutorObject *executor; + _PyFrame_SetStackPointer(frame, stack_pointer); int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer, &executor, 0); + stack_pointer = _PyFrame_GetStackPointer(frame); if (optimized < 0) goto error; if (optimized) { assert(tstate->previous_executor == NULL); @@ -4782,8 +5170,9 @@ _PyStackRef v; v = stack_pointer[-1]; list = stack_pointer[-2 - (oparg-1)]; - if (_PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), - PyStackRef_AsPyObjectSteal(v)) < 0) goto pop_1_error; + int err = _PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), + PyStackRef_AsPyObjectSteal(v)); + if (err < 0) goto pop_1_error; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -4799,16 +5188,22 @@ list_st = stack_pointer[-2 - (oparg-1)]; PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); PyObject *iterable = PyStackRef_AsPyObjectBorrow(iterable_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); if (none_val == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_TypeError); + stack_pointer = _PyFrame_GetStackPointer(frame); if (matches && (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable))) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Clear(tstate); _PyErr_Format(tstate, PyExc_TypeError, "Value after * must be an iterable, not %.200s", Py_TYPE(iterable)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); } PyStackRef_CLOSE(iterable_st); if (true) goto pop_1_error; @@ -4831,15 +5226,17 @@ _PyStackRef attr; _PyStackRef self_or_null = PyStackRef_NULL; // _SPECIALIZE_LOAD_ATTR - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_LoadAttr(owner, next_instr, name); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(LOAD_ATTR); @@ -4854,7 +5251,9 @@ if (oparg & 1) { /* Designed to work in tandem with CALL, pushes two values. */ attr_o = NULL; + _PyFrame_SetStackPointer(frame, stack_pointer); int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (is_meth) { /* We can bypass temporary bound method object. meth is unbound method and obj is self. @@ -4877,9 +5276,13 @@ } else { /* Classic, pushes one value. */ + _PyFrame_SetStackPointer(frame, stack_pointer); attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(owner); if (attr_o == NULL) goto pop_1_error; + /* We need to define self_or_null on all paths */ + self_or_null = PyStackRef_NULL; } attr = PyStackRef_FromPyObjectSteal(attr_o); } @@ -4900,8 +5303,8 @@ _PyStackRef null = PyStackRef_NULL; /* Skip 1 cache entry */ // _CHECK_ATTR_CLASS - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); DEOPT_IF(!PyType_Check(owner_o), LOAD_ATTR); @@ -4915,10 +5318,10 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; null = PyStackRef_NULL; PyStackRef_CLOSE(owner); } + stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -4935,8 +5338,8 @@ _PyStackRef null = PyStackRef_NULL; /* Skip 1 cache entry */ // _CHECK_ATTR_CLASS - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); DEOPT_IF(!PyType_Check(owner_o), LOAD_ATTR); @@ -4956,10 +5359,10 @@ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; null = PyStackRef_NULL; PyStackRef_CLOSE(owner); } + stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -5012,8 +5415,8 @@ _PyStackRef null = PyStackRef_NULL; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5057,8 +5460,8 @@ _PyStackRef self = PyStackRef_NULL; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5081,9 +5484,9 @@ assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; self = owner; } + stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -5100,8 +5503,8 @@ _PyStackRef self = PyStackRef_NULL; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5117,9 +5520,9 @@ assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; self = owner; } + stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -5136,8 +5539,8 @@ _PyStackRef self = PyStackRef_NULL; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5165,9 +5568,9 @@ assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; self = owner; } + stack_pointer[-1] = attr; stack_pointer[0] = self; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -5184,8 +5587,8 @@ _PyStackRef null = PyStackRef_NULL; /* Skip 1 cache entry */ // _CHECK_ATTR_MODULE - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t dict_version = read_u32(&this_instr[2].cache); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); DEOPT_IF(!PyModule_CheckExact(owner_o), LOAD_ATTR); @@ -5226,8 +5629,8 @@ _PyStackRef attr; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5243,8 +5646,8 @@ assert(descr != NULL); PyStackRef_CLOSE(owner); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; } + stack_pointer[-1] = attr; DISPATCH(); } @@ -5257,8 +5660,8 @@ _PyStackRef attr; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5285,8 +5688,8 @@ assert(descr != NULL); PyStackRef_CLOSE(owner); attr = PyStackRef_FromPyObjectNew(descr); - stack_pointer[-1] = attr; } + stack_pointer[-1] = attr; DISPATCH(); } @@ -5303,8 +5706,8 @@ DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); } // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5340,12 +5743,13 @@ // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -5364,8 +5768,8 @@ _PyStackRef null = PyStackRef_NULL; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5381,10 +5785,10 @@ STAT_INC(LOAD_ATTR, hit); null = PyStackRef_NULL; attr = PyStackRef_FromPyObjectNew(attr_o); - stack_pointer[-1] = attr; PyStackRef_CLOSE(owner); } /* Skip 5 cache entries */ + stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = null; stack_pointer += (oparg & 1); assert(WITHIN_STACK_BOUNDS()); @@ -5401,8 +5805,8 @@ _PyStackRef null = PyStackRef_NULL; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -5449,10 +5853,15 @@ INSTRUCTION_STATS(LOAD_BUILD_CLASS); _PyStackRef bc; PyObject *bc_o; - if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o) < 0) goto error; + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) goto error; if (bc_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_NameError, "__build_class__ not found"); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) goto error; } bc = PyStackRef_FromPyObjectSteal(bc_o); @@ -5468,16 +5877,16 @@ INSTRUCTION_STATS(LOAD_COMMON_CONSTANT); _PyStackRef value; // Keep in sync with _common_constants in opcode.py - switch(oparg) { - case CONSTANT_ASSERTIONERROR: - value = PyStackRef_FromPyObjectImmortal(PyExc_AssertionError); - break; - case CONSTANT_NOTIMPLEMENTEDERROR: - value = PyStackRef_FromPyObjectImmortal(PyExc_NotImplementedError); - break; - default: - Py_FatalError("bad LOAD_COMMON_CONSTANT oparg"); + // If we ever have more than two constants, use a lookup table + PyObject *val; + if (oparg == CONSTANT_ASSERTIONERROR) { + val = PyExc_AssertionError; + } + else { + assert(oparg == CONSTANT_NOTIMPLEMENTEDERROR); + val = PyExc_NotImplementedError; } + value = PyStackRef_FromPyObjectImmortal(val); stack_pointer[0] = value; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -5504,7 +5913,9 @@ PyCellObject *cell = (PyCellObject *)PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); PyObject *value_o = PyCell_GetRef(cell); if (value_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) goto error; } value = PyStackRef_FromPyObjectSteal(value_o); @@ -5548,10 +5959,12 @@ _PyStackRef value; _PyStackRef value_s = GETLOCAL(oparg); if (PyStackRef_IsNull(value_s)) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (1) goto error; } value = PyStackRef_DUP(value_s); @@ -5591,7 +6004,9 @@ assert(class_dict); assert(oparg >= 0 && oparg < _PyFrame_GetCode(frame)->co_nlocalsplus); name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(class_dict, name, &value_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { goto error; } @@ -5599,7 +6014,9 @@ PyCellObject *cell = (PyCellObject *)PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); value_o = PyCell_GetRef(cell); if (value_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); goto error; } } @@ -5618,23 +6035,30 @@ mod_or_class_dict = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *v_o; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &v_o); - if (err < 0) { - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + PyStackRef_CLOSE(mod_or_class_dict); + if (err < 0) goto pop_1_error; if (v_o == NULL) { if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); v_o = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(), (PyDictObject *)BUILTINS(), name); + stack_pointer = _PyFrame_GetStackPointer(frame); if (v_o == NULL) { if (!_PyErr_Occurred(tstate)) { /* _PyDict_LoadGlobal() returns NULL without raising * an exception if the key doesn't exist */ + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); + stack_pointer = _PyFrame_GetStackPointer(frame); } goto error; } @@ -5642,20 +6066,31 @@ else { /* Slow-path if globals or builtins is not a dict */ /* namespace 1: globals */ - if (PyMapping_GetOptionalItem(GLOBALS(), name, &v_o) < 0) goto pop_1_error; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyMapping_GetOptionalItem(GLOBALS(), name, &v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) goto error; if (v_o == NULL) { /* namespace 2: builtins */ - if (PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0) goto pop_1_error; + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyMapping_GetOptionalItem(BUILTINS(), name, &v_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) goto error; if (v_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - if (true) goto pop_1_error; + stack_pointer = _PyFrame_GetStackPointer(frame); + if (true) goto error; } } } + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } - PyStackRef_CLOSE(mod_or_class_dict); v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[-1] = v; DISPATCH(); @@ -5678,7 +6113,9 @@ if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(LOAD_GLOBAL); @@ -5692,7 +6129,9 @@ { res = &stack_pointer[0]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res); + stack_pointer = _PyFrame_GetStackPointer(frame); if (PyStackRef_IsNull(*res)) goto error; null = PyStackRef_NULL; } @@ -5788,8 +6227,10 @@ _PyStackRef locals; PyObject *l = LOCALS(); if (l == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_SystemError, "no locals found"); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) goto error; } locals = PyStackRef_FromPyObjectNew(l); @@ -5805,7 +6246,9 @@ INSTRUCTION_STATS(LOAD_NAME); _PyStackRef v; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *v_o = _PyEval_LoadName(tstate, frame, name); + stack_pointer = _PyFrame_GetStackPointer(frame); if (v_o == NULL) goto error; v = PyStackRef_FromPyObjectSteal(v_o); stack_pointer[0] = v; @@ -5826,19 +6269,27 @@ PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner); PyObject *name = _Py_SpecialMethods[oparg].name; PyObject *self_or_null_o; - attr = PyStackRef_FromPyObjectSteal(_PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o)); - if (PyStackRef_IsNull(attr)) { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (attr_o == NULL) { if (!_PyErr_Occurred(tstate)) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_TypeError, _Py_SpecialMethods[oparg].error, Py_TYPE(owner_o)->tp_name); + stack_pointer = _PyFrame_GetStackPointer(frame); } + if (true) goto error; } - if (PyStackRef_IsNull(attr)) goto pop_1_error; - self_or_null = PyStackRef_FromPyObjectSteal(self_or_null_o); - stack_pointer[-1] = attr; - stack_pointer[0] = self_or_null; - stack_pointer += 1; + attr = PyStackRef_FromPyObjectSteal(attr_o); + self_or_null = self_or_null_o == NULL ? + PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o); + stack_pointer[0] = attr; + stack_pointer[1] = self_or_null; + stack_pointer += 2; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5856,16 +6307,18 @@ _PyStackRef attr; _PyStackRef null = PyStackRef_NULL; // _SPECIALIZE_LOAD_SUPER_ATTR - class_st = stack_pointer[-2]; - global_super_st = stack_pointer[-3]; { + class_st = stack_pointer[-2]; + global_super_st = stack_pointer[-3]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION int load_method = oparg & 1; if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_LoadSuperAttr(global_super_st, class_st, next_instr, load_method); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(LOAD_SUPER_ATTR); @@ -5873,33 +6326,46 @@ #endif /* ENABLE_SPECIALIZATION */ } // _LOAD_SUPER_ATTR - self_st = stack_pointer[-1]; { + self_st = stack_pointer[-1]; PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); PyObject *class = PyStackRef_AsPyObjectBorrow(class_st); PyObject *self = PyStackRef_AsPyObjectBorrow(self_st); if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, global_super, arg); - if (err) goto pop_3_error; + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + PyStackRef_CLOSE(global_super_st); + PyStackRef_CLOSE(class_st); + PyStackRef_CLOSE(self_st); + if (true) goto pop_3_error; + } } // we make no attempt to optimize here; specializations should // handle any case whose performance we care about PyObject *stack[] = {class, self}; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) { PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING; if (super == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_call_instrumentation_exc2( tstate, PY_MONITORING_EVENT_C_RAISE, frame, this_instr, global_super, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_C_RETURN, frame, this_instr, global_super, arg); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err < 0) { Py_CLEAR(super); } @@ -5910,14 +6376,19 @@ PyStackRef_CLOSE(self_st); if (super == NULL) goto pop_3_error; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); - attr = PyStackRef_FromPyObjectSteal(PyObject_GetAttr(super, name)); + stack_pointer += -3; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *attr_o = PyObject_GetAttr(super, name); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(super); - if (PyStackRef_IsNull(attr)) goto pop_3_error; + if (attr_o == NULL) goto error; + attr = PyStackRef_FromPyObjectSteal(attr_o); null = PyStackRef_NULL; } - stack_pointer[-3] = attr; - if (oparg & 1) stack_pointer[-2] = null; - stack_pointer += -2 + (oparg & 1); + stack_pointer[0] = attr; + if (oparg & 1) stack_pointer[1] = null; + stack_pointer += 1 + (oparg & 1); assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } @@ -5943,7 +6414,9 @@ DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR); STAT_INC(LOAD_SUPER_ATTR, hit); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(global_super_st); PyStackRef_CLOSE(class_st); PyStackRef_CLOSE(self_st); @@ -5979,8 +6452,10 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyTypeObject *cls = (PyTypeObject *)class; int method_found = 0; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attr_o = _PySuper_Lookup(cls, self, name, Py_TYPE(self)->tp_getattro == PyObject_GenericGetAttr ? &method_found : NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(global_super_st); PyStackRef_CLOSE(class_st); if (attr_o == NULL) { @@ -6024,12 +6499,12 @@ _PyStackRef func; codeobj_st = stack_pointer[-1]; PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); + _PyFrame_SetStackPointer(frame, stack_pointer); PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(codeobj_st); - if (func_obj == NULL) { - goto error; - } + if (func_obj == NULL) goto pop_1_error; _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); func = PyStackRef_FromPyObjectSteal((PyObject *)func_obj); @@ -6051,11 +6526,13 @@ assert(PyDict_CheckExact(dict)); /* dict[key] = value */ // Do not DECREF INPUTS because the function steals the references + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_SetItem_Take2( (PyDictObject *)dict, PyStackRef_AsPyObjectSteal(key), PyStackRef_AsPyObjectSteal(value) ); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) goto pop_2_error; stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -6076,10 +6553,12 @@ // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attrs_o = _PyEval_MatchClass(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(type), oparg, PyStackRef_AsPyObjectBorrow(names)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(subject); PyStackRef_CLOSE(type); PyStackRef_CLOSE(names); @@ -6108,8 +6587,10 @@ keys = stack_pointer[-1]; subject = stack_pointer[-2]; // On successful match, PUSH(values). Otherwise, PUSH(None). + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *values_or_none_o = _PyEval_MatchKeys(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(keys)); + stack_pointer = _PyFrame_GetStackPointer(frame); if (values_or_none_o == NULL) goto error; values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o); stack_pointer[0] = values_or_none; @@ -6162,9 +6643,11 @@ _PyStackRef exc_value; exc_value = stack_pointer[-1]; _PyErr_StackItem *exc_info = tstate->exc_info; + _PyFrame_SetStackPointer(frame, stack_pointer); Py_XSETREF(exc_info->exc_value, PyStackRef_Is(exc_value, PyStackRef_None) ? NULL : PyStackRef_AsPyObjectSteal(exc_value)); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -6199,8 +6682,8 @@ _PyStackRef cond; /* Skip 1 cache entry */ // _IS_NONE - value = stack_pointer[-1]; { + value = stack_pointer[-1]; if (PyStackRef_Is(value, PyStackRef_None)) { b = PyStackRef_True; } @@ -6210,8 +6693,8 @@ } } // _POP_JUMP_IF_TRUE - cond = b; { + cond = b; assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_Is(cond, PyStackRef_True); #if ENABLE_SPECIALIZATION @@ -6234,8 +6717,8 @@ _PyStackRef cond; /* Skip 1 cache entry */ // _IS_NONE - value = stack_pointer[-1]; { + value = stack_pointer[-1]; if (PyStackRef_Is(value, PyStackRef_None)) { b = PyStackRef_True; } @@ -6245,8 +6728,8 @@ } } // _POP_JUMP_IF_FALSE - cond = b; { + cond = b; assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_Is(cond, PyStackRef_False); #if ENABLE_SPECIALIZATION @@ -6294,9 +6777,10 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(PUSH_EXC_INFO); - _PyStackRef new_exc; + _PyStackRef exc; _PyStackRef prev_exc; - new_exc = stack_pointer[-1]; + _PyStackRef new_exc; + exc = stack_pointer[-1]; _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { prev_exc = PyStackRef_FromPyObjectSteal(exc_info->exc_value); @@ -6304,8 +6788,9 @@ else { prev_exc = PyStackRef_None; } - assert(PyStackRef_ExceptionInstanceCheck(new_exc)); - exc_info->exc_value = PyStackRef_AsPyObjectNew(new_exc); + assert(PyStackRef_ExceptionInstanceCheck(exc)); + exc_info->exc_value = PyStackRef_AsPyObjectNew(exc); + new_exc = exc; stack_pointer[-1] = prev_exc; stack_pointer[0] = new_exc; stack_pointer += 1; @@ -6332,31 +6817,22 @@ INSTRUCTION_STATS(RAISE_VARARGS); _PyStackRef *args; args = &stack_pointer[-oparg]; - PyObject *cause = NULL, *exc = NULL; - switch (oparg) { - case 2: - cause = PyStackRef_AsPyObjectSteal(args[1]); - _Py_FALLTHROUGH; - case 1: - exc = PyStackRef_AsPyObjectSteal(args[0]); - _Py_FALLTHROUGH; - case 0: - if (do_raise(tstate, exc, cause)) { - assert(oparg == 0); - monitor_reraise(tstate, frame, this_instr); - goto exception_unwind; - } - break; - default: - _PyErr_SetString(tstate, PyExc_SystemError, - "bad RAISE_VARARGS oparg"); - break; - } - if (true) { - stack_pointer += -oparg; - assert(WITHIN_STACK_BOUNDS()); - goto error; + assert(oparg < 3); + PyObject *cause = oparg == 2 ? PyStackRef_AsPyObjectSteal(args[1]) : NULL; + PyObject *exc = oparg > 0 ? PyStackRef_AsPyObjectSteal(args[0]) : NULL; + stack_pointer += -oparg; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = do_raise(tstate, exc, cause); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err) { + assert(oparg == 0); + _PyFrame_SetStackPointer(frame, stack_pointer); + monitor_reraise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + goto exception_unwind; } + if (true) goto error; } TARGET(RERAISE) { @@ -6368,7 +6844,7 @@ _PyStackRef exc_st; exc_st = stack_pointer[-1]; values = &stack_pointer[-1 - oparg]; - PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); + PyObject *exc = PyStackRef_AsPyObjectSteal(exc_st); assert(oparg >= 0 && oparg <= 2); if (oparg) { PyObject *lasti = PyStackRef_AsPyObjectBorrow(values[0]); @@ -6377,14 +6853,22 @@ assert(!_PyErr_Occurred(tstate)); } else { + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); + stack_pointer = _PyFrame_GetStackPointer(frame); + Py_DECREF(exc); goto error; } } assert(exc && PyExceptionInstance_Check(exc)); - Py_INCREF(exc); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetRaisedException(tstate, exc); monitor_reraise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); goto exception_unwind; } @@ -6410,7 +6894,9 @@ uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK; uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version); if (code_version != global_version) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err) { goto error; } @@ -6433,7 +6919,9 @@ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); \ if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err != 0) goto error; } } @@ -6467,14 +6955,14 @@ // _LOAD_CONST { value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg)); - stack_pointer[0] = value; } // _RETURN_VALUE - retval = value; { + retval = value; #if TIER_ONE assert(frame != &entry_frame); #endif + _PyStackRef temp = retval; _PyFrame_SetStackPointer(frame, stack_pointer); assert(EMPTY()); _Py_LeaveRecursiveCallPy(tstate); @@ -6482,9 +6970,9 @@ _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(frame->return_offset); - res = retval; + res = temp; LLTRACE_RESUME_FRAME(); } stack_pointer[0] = res; @@ -6500,10 +6988,10 @@ _PyStackRef res; assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); + _PyFrame_SetStackPointer(frame, stack_pointer); PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - if (gen == NULL) { - goto error; - } + stack_pointer = _PyFrame_GetStackPointer(frame); + if (gen == NULL) goto error; assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *gen_frame = &gen->gi_iframe; @@ -6513,12 +7001,12 @@ gen->gi_frame_state = FRAME_CREATED; gen_frame->owner = FRAME_OWNED_BY_GENERATOR; _Py_LeaveRecursiveCallPy(tstate); - res = PyStackRef_FromPyObjectSteal((PyObject *)gen); _PyInterpreterFrame *prev = frame->previous; _PyThreadState_PopFrame(tstate, frame); frame = tstate->current_frame = prev; LOAD_IP(frame->return_offset); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); + res = PyStackRef_FromPyObjectSteal((PyObject *)gen); LLTRACE_RESUME_FRAME(); stack_pointer[0] = res; stack_pointer += 1; @@ -6536,6 +7024,7 @@ #if TIER_ONE assert(frame != &entry_frame); #endif + _PyStackRef temp = retval; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -6545,9 +7034,9 @@ _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); - LOAD_SP(); + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(frame->return_offset); - res = retval; + res = temp; LLTRACE_RESUME_FRAME(); stack_pointer[0] = res; stack_pointer += 1; @@ -6566,14 +7055,16 @@ _PyStackRef v; _PyStackRef retval; // _SPECIALIZE_SEND - receiver = stack_pointer[-2]; { + receiver = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_Send(receiver, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(SEND); @@ -6581,8 +7072,8 @@ #endif /* ENABLE_SPECIALIZATION */ } // _SEND - v = stack_pointer[-1]; { + v = stack_pointer[-1]; PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *retval_o; assert(frame != &entry_frame); @@ -6604,25 +7095,36 @@ DISPATCH_INLINED(gen_frame); } if (PyStackRef_Is(v, PyStackRef_None) && PyIter_Check(receiver_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); retval_o = Py_TYPE(receiver_o)->tp_iternext(receiver_o); + stack_pointer = _PyFrame_GetStackPointer(frame); } else { + _PyFrame_SetStackPointer(frame, stack_pointer); retval_o = PyObject_CallMethodOneArg(receiver_o, &_Py_ID(send), PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); } if (retval_o == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); int matches = _PyErr_ExceptionMatches(tstate, PyExc_StopIteration); + stack_pointer = _PyFrame_GetStackPointer(frame); if (matches) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_MonitorRaise(tstate, frame, this_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); } + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyGen_FetchStopIterationValue(&retval_o); + stack_pointer = _PyFrame_GetStackPointer(frame); if (err == 0) { assert(retval_o != NULL); JUMPBY(oparg); } else { - goto error; + PyStackRef_CLOSE(v); + if (true) goto pop_1_error; } } PyStackRef_CLOSE(v); @@ -6647,9 +7149,9 @@ DEOPT_IF(tstate->interp->eval_frame, SEND); } // _SEND_GEN_FRAME - v = stack_pointer[-1]; - receiver = stack_pointer[-2]; { + v = stack_pointer[-1]; + receiver = stack_pointer[-2]; PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(receiver); DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != &PyCoro_Type, SEND); DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING, SEND); @@ -6664,17 +7166,18 @@ gen_frame->previous = frame; } // _PUSH_FRAME - new_frame = gen_frame; { + new_frame = gen_frame; // Write it out explicitly because it's subtly different. // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); + _PyInterpreterFrame *temp = new_frame; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); assert(new_frame->previous == frame || new_frame->previous->previous == frame); CALL_STAT_INC(inlined_py_calls); - frame = tstate->current_frame = new_frame; + frame = tstate->current_frame = temp; tstate->py_recursion_remaining--; LOAD_SP(); LOAD_IP(0); @@ -6687,20 +7190,28 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(SETUP_ANNOTATIONS); - int err; PyObject *ann_dict; if (LOCALS() == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_SystemError, "no locals found when setting up annotations"); + stack_pointer = _PyFrame_GetStackPointer(frame); if (true) goto error; } /* check if __annotations__ in locals()... */ - if (PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict) < 0) goto error; + _PyFrame_SetStackPointer(frame, stack_pointer); + int err = PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (err < 0) goto error; if (ann_dict == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); ann_dict = PyDict_New(); + stack_pointer = _PyFrame_GetStackPointer(frame); if (ann_dict == NULL) goto error; + _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), ann_dict); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(ann_dict); if (err) goto error; } @@ -6718,8 +7229,10 @@ _PyStackRef v; v = stack_pointer[-1]; set = stack_pointer[-2 - (oparg-1)]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); if (err) goto pop_1_error; stack_pointer += -1; @@ -6732,41 +7245,20 @@ next_instr += 1; INSTRUCTION_STATS(SET_FUNCTION_ATTRIBUTE); _PyStackRef attr_st; - _PyStackRef func_st; - func_st = stack_pointer[-1]; + _PyStackRef func_in; + _PyStackRef func_out; + func_in = stack_pointer[-1]; attr_st = stack_pointer[-2]; - PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - PyObject *attr = PyStackRef_AsPyObjectBorrow(attr_st); + PyObject *func = PyStackRef_AsPyObjectBorrow(func_in); + PyObject *attr = PyStackRef_AsPyObjectSteal(attr_st); + func_out = func_in; assert(PyFunction_Check(func)); - PyFunctionObject *func_obj = (PyFunctionObject *)func; - switch(oparg) { - case MAKE_FUNCTION_CLOSURE: - assert(func_obj->func_closure == NULL); - func_obj->func_closure = attr; - break; - case MAKE_FUNCTION_ANNOTATIONS: - assert(func_obj->func_annotations == NULL); - func_obj->func_annotations = attr; - break; - case MAKE_FUNCTION_KWDEFAULTS: - assert(PyDict_CheckExact(attr)); - assert(func_obj->func_kwdefaults == NULL); - func_obj->func_kwdefaults = attr; - break; - case MAKE_FUNCTION_DEFAULTS: - assert(PyTuple_CheckExact(attr)); - assert(func_obj->func_defaults == NULL); - func_obj->func_defaults = attr; - break; - case MAKE_FUNCTION_ANNOTATE: - assert(PyCallable_Check(attr)); - assert(func_obj->func_annotate == NULL); - func_obj->func_annotate = attr; - break; - default: - Py_UNREACHABLE(); - } - stack_pointer[-2] = func_st; + size_t offset = _Py_FunctionAttributeOffsets[oparg]; + assert(offset != 0); + PyObject **ptr = (PyObject **)(((char *)func) + offset); + assert(*ptr == NULL); + *ptr = attr; + stack_pointer[-2] = func_out; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -6780,8 +7272,10 @@ _PyStackRef iterable; iterable = stack_pointer[-1]; set = stack_pointer[-2 - (oparg-1)]; + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(iterable); if (err < 0) goto pop_1_error; stack_pointer += -1; @@ -6799,15 +7293,17 @@ _PyStackRef owner; _PyStackRef v; // _SPECIALIZE_STORE_ATTR - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_StoreAttr(owner, next_instr, name); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(STORE_ATTR); @@ -6816,11 +7312,13 @@ } /* Skip 3 cache entries */ // _STORE_ATTR - v = stack_pointer[-2]; { + v = stack_pointer[-2]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetAttr(PyStackRef_AsPyObjectBorrow(owner), name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); PyStackRef_CLOSE(owner); if (err) goto pop_2_error; @@ -6839,8 +7337,8 @@ _PyStackRef value; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); @@ -6855,8 +7353,8 @@ DEOPT_IF(_PyObject_InlineValues(owner_o)->valid == 0, STORE_ATTR); } // _STORE_ATTR_INSTANCE_VALUE - value = stack_pointer[-2]; { + value = stack_pointer[-2]; uint16_t offset = read_u16(&this_instr[4].cache); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); STAT_INC(STORE_ATTR, hit); @@ -6888,16 +7386,16 @@ _PyStackRef value; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); } // _STORE_ATTR_SLOT - value = stack_pointer[-2]; { + value = stack_pointer[-2]; uint16_t index = read_u16(&this_instr[4].cache); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); char *addr = (char *)owner_o + index; @@ -6921,16 +7419,16 @@ _PyStackRef value; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR); } // _STORE_ATTR_WITH_HINT - value = stack_pointer[-2]; { + value = stack_pointer[-2]; uint16_t hint = read_u16(&this_instr[4].cache); PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner); assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -6940,7 +7438,6 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR); PyObject *old_value; - uint64_t new_version; DEOPT_IF(!DK_IS_UNICODE(dict->ma_keys), STORE_ATTR); PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; DEOPT_IF(ep->me_key != name, STORE_ATTR); @@ -6950,9 +7447,10 @@ } old_value = ep->me_value; PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED; - new_version = _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value)); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); ep->me_value = PyStackRef_AsPyObjectSteal(value); - dict->ma_version_tag = new_version; // PEP 509 // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault, // when dict only holds the strong reference to value in ep->me_value. Py_XDECREF(old_value); @@ -6971,7 +7469,9 @@ _PyStackRef v; v = stack_pointer[-1]; PyCellObject *cell = (PyCellObject *)PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); + _PyFrame_SetStackPointer(frame, stack_pointer); PyCell_SetTakeRef(cell, PyStackRef_AsPyObjectSteal(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -7028,7 +7528,9 @@ _PyStackRef v; v = stack_pointer[-1]; PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_SetItem(GLOBALS(), name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); if (err) goto pop_1_error; stack_pointer += -1; @@ -7046,15 +7548,23 @@ PyObject *ns = LOCALS(); int err; if (ns == NULL) { + _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); if (true) goto pop_1_error; } - if (PyDict_CheckExact(ns)) - err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); - else - err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + if (PyDict_CheckExact(ns)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); + } PyStackRef_CLOSE(v); if (err) goto pop_1_error; stack_pointer += -1; @@ -7078,20 +7588,28 @@ #endif /* ENABLE_SPECIALIZATION */ } // _STORE_SLICE - stop = stack_pointer[-1]; - start = stack_pointer[-2]; - container = stack_pointer[-3]; - v = stack_pointer[-4]; { + stop = stack_pointer[-1]; + start = stack_pointer[-2]; + container = stack_pointer[-3]; + v = stack_pointer[-4]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *slice = _PyBuildSlice_ConsumeRefs(PyStackRef_AsPyObjectSteal(start), PyStackRef_AsPyObjectSteal(stop)); + stack_pointer = _PyFrame_GetStackPointer(frame); int err; if (slice == NULL) { err = 1; } else { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), slice, PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); Py_DECREF(slice); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } PyStackRef_CLOSE(v); PyStackRef_CLOSE(container); @@ -7113,15 +7631,17 @@ _PyStackRef sub; _PyStackRef v; // _SPECIALIZE_STORE_SUBSCR - sub = stack_pointer[-1]; - container = stack_pointer[-2]; { + sub = stack_pointer[-1]; + container = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_StoreSubscr(container, sub, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(STORE_SUBSCR); @@ -7129,10 +7649,12 @@ #endif /* ENABLE_SPECIALIZATION */ } // _STORE_SUBSCR - v = stack_pointer[-3]; { + v = stack_pointer[-3]; /* container[sub] = v */ + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(v); PyStackRef_CLOSE(container); PyStackRef_CLOSE(sub); @@ -7158,9 +7680,11 @@ PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR); STAT_INC(STORE_SUBSCR, hit); + _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_SetItem_Take2((PyDictObject *)dict, PyStackRef_AsPyObjectSteal(sub), PyStackRef_AsPyObjectSteal(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(dict_st); if (err) goto pop_3_error; stack_pointer += -3; @@ -7205,13 +7729,17 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(SWAP); - _PyStackRef bottom; - _PyStackRef top; - top = stack_pointer[-1]; - bottom = stack_pointer[-2 - (oparg-2)]; + _PyStackRef bottom_in; + _PyStackRef top_in; + _PyStackRef top_out; + _PyStackRef bottom_out; + top_in = stack_pointer[-1]; + bottom_in = stack_pointer[-2 - (oparg-2)]; + bottom_out = bottom_in; + top_out = top_in; assert(oparg >= 2); - stack_pointer[-2 - (oparg-2)] = top; - stack_pointer[-1] = bottom; + stack_pointer[-2 - (oparg-2)] = top_out; + stack_pointer[-1] = bottom_out; DISPATCH(); } @@ -7225,14 +7753,16 @@ _PyStackRef value; _PyStackRef res; // _SPECIALIZE_TO_BOOL - value = stack_pointer[-1]; { + value = stack_pointer[-1]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_ToBool(value, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(TO_BOOL); @@ -7242,7 +7772,9 @@ /* Skip 2 cache entries */ // _TO_BOOL { + _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (err < 0) goto pop_1_error; res = err ? PyStackRef_True : PyStackRef_False; @@ -7261,16 +7793,16 @@ _PyStackRef res; /* Skip 1 cache entry */ // _GUARD_TYPE_VERSION - owner = stack_pointer[-1]; { + owner = stack_pointer[-1]; uint32_t type_version = read_u32(&this_instr[2].cache); PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(owner)); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, TO_BOOL); } // _REPLACE_WITH_TRUE - value = owner; { + value = owner; PyStackRef_CLOSE(value); res = PyStackRef_True; } @@ -7387,7 +7919,9 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (res_o == NULL) goto pop_1_error; res = PyStackRef_FromPyObjectSteal(res_o); @@ -7402,7 +7936,9 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; + _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value)); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(value); if (res_o == NULL) goto pop_1_error; res = PyStackRef_FromPyObjectSteal(res_o); @@ -7433,7 +7969,9 @@ seq = stack_pointer[-1]; right = &stack_pointer[(oparg & 0xFF)]; _PyStackRef *top = right + (oparg >> 8); + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg & 0xFF, oparg >> 8, top); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(seq); if (res == 0) goto pop_1_error; stack_pointer += (oparg & 0xFF) + (oparg >> 8); @@ -7451,14 +7989,16 @@ _PyStackRef seq; _PyStackRef *output; // _SPECIALIZE_UNPACK_SEQUENCE - seq = stack_pointer[-1]; { + seq = stack_pointer[-1]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; #if ENABLE_SPECIALIZATION if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); _Py_Specialize_UnpackSequence(seq, next_instr, oparg); + stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(UNPACK_SEQUENCE); @@ -7471,7 +8011,9 @@ { output = &stack_pointer[-1]; _PyStackRef *top = output + oparg; + _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PyEval_UnpackIterableStackRef(tstate, seq, oparg, -1, top); + stack_pointer = _PyFrame_GetStackPointer(frame); PyStackRef_CLOSE(seq); if (res == 0) goto pop_1_error; } @@ -7544,10 +8086,10 @@ DEOPT_IF(PyTuple_GET_SIZE(seq_o) != 2, UNPACK_SEQUENCE); STAT_INC(UNPACK_SEQUENCE, hit); val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0)); - stack_pointer[0] = val0; val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1)); - stack_pointer[-1] = val1; PyStackRef_CLOSE(seq); + stack_pointer[-1] = val1; + stack_pointer[0] = val0; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -7591,9 +8133,12 @@ (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb}; int has_self = !PyStackRef_IsNull(exit_self); - res = PyStackRef_FromPyObjectSteal(PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, - (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL)); - if (PyStackRef_IsNull(res)) goto error; + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *res_o = PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, + (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (res_o == NULL) goto error; + res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -7618,6 +8163,7 @@ assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1); assert(oparg == 0 || oparg == 1); gen->gi_frame_state = FRAME_SUSPENDED + oparg; + _PyStackRef temp = retval; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7631,113 +8177,19 @@ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || - frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || - _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); + frame->instr_ptr->op.code == INSTRUMENTED_INSTRUCTION || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == SEND || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == FOR_ITER || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == INTERPRETER_EXIT || + _PyOpcode_Deopt[frame->instr_ptr->op.code] == ENTER_EXECUTOR); #endif + stack_pointer = _PyFrame_GetStackPointer(frame); LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND); - LOAD_SP(); - value = retval; + value = temp; LLTRACE_RESUME_FRAME(); stack_pointer[0] = value; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); } - - TARGET(_DO_CALL_FUNCTION_EX) { - _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr; - (void)this_instr; - next_instr += 1; - INSTRUCTION_STATS(_DO_CALL_FUNCTION_EX); - _PyStackRef func_st; - _PyStackRef callargs_st; - _PyStackRef kwargs_st = PyStackRef_NULL; - _PyStackRef result; - if (oparg & 1) { kwargs_st = stack_pointer[-(oparg & 1)]; } - callargs_st = stack_pointer[-1 - (oparg & 1)]; - func_st = stack_pointer[-3 - (oparg & 1)]; - PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st); - PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st); - // DICT_MERGE is called before this opcode if there are kwargs. - // It converts all dict subtypes in kwargs into regular dicts. - assert(kwargs == NULL || PyDict_CheckExact(kwargs)); - if (!PyTuple_CheckExact(callargs)) { - int err = check_args_iterable(tstate, func, callargs); - if (err < 0) { - goto error; - } - PyObject *tuple = PySequence_Tuple(callargs); - if (tuple == NULL) { - goto error; - } - PyStackRef_CLOSE(callargs_st); - callargs_st = PyStackRef_FromPyObjectSteal(tuple); - callargs = tuple; - } - assert(PyTuple_CheckExact(callargs)); - EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); - if (opcode == INSTRUMENTED_CALL_FUNCTION_EX) { - PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ? - PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING; - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_CALL, - frame, this_instr, func, arg); - if (err) goto error; - result = PyStackRef_FromPyObjectSteal(PyObject_Call(func, callargs, kwargs)); - if (!PyFunction_Check(func) && !PyMethod_Check(func)) { - if (PyStackRef_IsNull(result)) { - _Py_call_instrumentation_exc2( - tstate, PY_MONITORING_EVENT_C_RAISE, - frame, this_instr, func, arg); - } - else { - int err = _Py_call_instrumentation_2args( - tstate, PY_MONITORING_EVENT_C_RETURN, - frame, this_instr, func, arg); - if (err < 0) { - PyStackRef_CLEAR(result); - } - } - } - } - else { - if (Py_TYPE(func) == &PyFunction_Type && - tstate->interp->eval_frame == NULL && - ((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) { - assert(PyTuple_CheckExact(callargs)); - Py_ssize_t nargs = PyTuple_GET_SIZE(callargs); - int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags; - PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func)); - _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex( - tstate, func_st, locals, - nargs, callargs, kwargs, frame); - // Need to manually shrink the stack since we exit with DISPATCH_INLINED. - STACK_SHRINK(oparg + 3); - if (new_frame == NULL) { - goto error; - } - assert(next_instr - this_instr == 1); - frame->return_offset = 1; - DISPATCH_INLINED(new_frame); - } - result = PyStackRef_FromPyObjectSteal(PyObject_Call(func, callargs, kwargs)); - } - PyStackRef_CLOSE(func_st); - PyStackRef_CLOSE(callargs_st); - PyStackRef_XCLOSE(kwargs_st); - assert(PyStackRef_AsPyObjectBorrow(PEEK(2 + (oparg & 1))) == NULL); - if (PyStackRef_IsNull(result)) { - stack_pointer += -3 - (oparg & 1); - assert(WITHIN_STACK_BOUNDS()); - goto error; - } - stack_pointer[-3 - (oparg & 1)] = result; - stack_pointer += -2 - (oparg & 1); - assert(WITHIN_STACK_BOUNDS()); - DISPATCH(); - } #undef TIER_ONE diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 5e51a9c992f6c2..e1e494c31a1120 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -643,8 +643,8 @@ de_instrument(PyCodeObject *code, int i, int event) CHECK(_PyOpcode_Deopt[deinstrumented] == deinstrumented); FT_ATOMIC_STORE_UINT8_RELAXED(*opcode_ptr, deinstrumented); if (_PyOpcode_Caches[deinstrumented]) { - FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.as_counter, - adaptive_counter_warmup().as_counter); + FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.value_and_backoff, + adaptive_counter_warmup().value_and_backoff); } } @@ -719,8 +719,8 @@ instrument(PyCodeObject *code, int i) assert(instrumented); FT_ATOMIC_STORE_UINT8_RELAXED(*opcode_ptr, instrumented); if (_PyOpcode_Caches[deopt]) { - FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.as_counter, - adaptive_counter_warmup().as_counter); + FT_ATOMIC_STORE_UINT16_RELAXED(instr[1].counter.value_and_backoff, + adaptive_counter_warmup().value_and_backoff); instr[1].counter = adaptive_counter_warmup(); } } @@ -1660,6 +1660,16 @@ update_instrumentation_data(PyCodeObject *code, PyInterpreterState *interp) if (allocate_instrumentation_data(code)) { return -1; } + // If the local monitors are out of date, clear them up + _Py_LocalMonitors *local_monitors = &code->_co_monitoring->local_monitors; + for (int i = 0; i < PY_MONITORING_TOOL_IDS; i++) { + if (code->_co_monitoring->tool_versions[i] != interp->monitoring_tool_versions[i]) { + for (int j = 0; j < _PY_MONITORING_LOCAL_EVENTS; j++) { + local_monitors->tools[j] &= ~(1 << i); + } + } + } + _Py_LocalMonitors all_events = local_union( interp->monitors, code->_co_monitoring->local_monitors); @@ -2004,6 +2014,8 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent goto done; } + code->_co_monitoring->tool_versions[tool_id] = interp->monitoring_tool_versions[tool_id]; + _Py_LocalMonitors *local = &code->_co_monitoring->local_monitors; uint32_t existing_events = get_local_events(local, tool_id); if (existing_events == events) { @@ -2036,6 +2048,43 @@ _PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringEvent return 0; } +int _PyMonitoring_ClearToolId(int tool_id) +{ + assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); + PyInterpreterState *interp = _PyInterpreterState_GET(); + + for (int i = 0; i < _PY_MONITORING_EVENTS; i++) { + PyObject *func = _PyMonitoring_RegisterCallback(tool_id, i, NULL); + if (func != NULL) { + Py_DECREF(func); + } + } + + if (_PyMonitoring_SetEvents(tool_id, 0) < 0) { + return -1; + } + + _PyEval_StopTheWorld(interp); + uint32_t version = global_version(interp) + MONITORING_VERSION_INCREMENT; + if (version == 0) { + PyErr_Format(PyExc_OverflowError, "events set too many times"); + _PyEval_StartTheWorld(interp); + return -1; + } + + // monitoring_tool_versions[tool_id] is set to latest global version here to + // 1. invalidate local events on all existing code objects + // 2. be ready for the next call to set local events + interp->monitoring_tool_versions[tool_id] = version; + + // Set the new global version so all the code objects can refresh the + // instrumentation. + set_global_version(_PyThreadState_GET(), version); + int res = instrument_all_executing_code_objects(interp); + _PyEval_StartTheWorld(interp); + return res; +} + /*[clinic input] module monitoring [clinic start generated code]*/ @@ -2083,6 +2132,33 @@ monitoring_use_tool_id_impl(PyObject *module, int tool_id, PyObject *name) Py_RETURN_NONE; } +/*[clinic input] +monitoring.clear_tool_id + + tool_id: int + / + +[clinic start generated code]*/ + +static PyObject * +monitoring_clear_tool_id_impl(PyObject *module, int tool_id) +/*[clinic end generated code: output=04defc23470b1be7 input=af643d6648a66163]*/ +{ + if (check_valid_tool(tool_id)) { + return NULL; + } + + PyInterpreterState *interp = _PyInterpreterState_GET(); + + if (interp->monitoring_tool_names[tool_id] != NULL) { + if (_PyMonitoring_ClearToolId(tool_id) < 0) { + return NULL; + } + } + + Py_RETURN_NONE; +} + /*[clinic input] monitoring.free_tool_id @@ -2099,6 +2175,13 @@ monitoring_free_tool_id_impl(PyObject *module, int tool_id) return NULL; } PyInterpreterState *interp = _PyInterpreterState_GET(); + + if (interp->monitoring_tool_names[tool_id] != NULL) { + if (_PyMonitoring_ClearToolId(tool_id) < 0) { + return NULL; + } + } + Py_CLEAR(interp->monitoring_tool_names[tool_id]); Py_RETURN_NONE; } @@ -2376,6 +2459,7 @@ monitoring__all_events_impl(PyObject *module) static PyMethodDef methods[] = { MONITORING_USE_TOOL_ID_METHODDEF + MONITORING_CLEAR_TOOL_ID_METHODDEF MONITORING_FREE_TOOL_ID_METHODDEF MONITORING_GET_TOOL_METHODDEF MONITORING_REGISTER_CALLBACK_METHODDEF diff --git a/Python/jit.c b/Python/jit.c index 33320761621c4c..234fc7dda83231 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_abstract.h" +#include "pycore_bitutils.h" #include "pycore_call.h" #include "pycore_ceval.h" #include "pycore_critical_section.h" @@ -113,6 +114,21 @@ mark_executable(unsigned char *memory, size_t size) // JIT compiler stuff: ///////////////////////////////////////////////////////// +#define SYMBOL_MASK_WORDS 4 + +typedef uint32_t symbol_mask[SYMBOL_MASK_WORDS]; + +typedef struct { + unsigned char *mem; + symbol_mask mask; + size_t size; +} trampoline_state; + +typedef struct { + trampoline_state trampolines; + uintptr_t instruction_starts[UOP_MAX_TRACE_LENGTH]; +} jit_state; + // Warning! AArch64 requires you to get your hands dirty. These are your gloves: // value[value_start : value_start + len] @@ -390,66 +406,126 @@ patch_x86_64_32rx(unsigned char *location, uint64_t value) patch_32r(location, value); } +void patch_aarch64_trampoline(unsigned char *location, int ordinal, jit_state *state); + #include "jit_stencils.h" +#if defined(__aarch64__) || defined(_M_ARM64) + #define TRAMPOLINE_SIZE 16 +#else + #define TRAMPOLINE_SIZE 0 +#endif + +// Generate and patch AArch64 trampolines. The symbols to jump to are stored +// in the jit_stencils.h in the symbols_map. +void +patch_aarch64_trampoline(unsigned char *location, int ordinal, jit_state *state) +{ + // Masking is done modulo 32 as the mask is stored as an array of uint32_t + const uint32_t symbol_mask = 1 << (ordinal % 32); + const uint32_t trampoline_mask = state->trampolines.mask[ordinal / 32]; + assert(symbol_mask & trampoline_mask); + + // Count the number of set bits in the trampoline mask lower than ordinal, + // this gives the index into the array of trampolines. + int index = _Py_popcount32(trampoline_mask & (symbol_mask - 1)); + for (int i = 0; i < ordinal / 32; i++) { + index += _Py_popcount32(state->trampolines.mask[i]); + } + + uint32_t *p = (uint32_t*)(state->trampolines.mem + index * TRAMPOLINE_SIZE); + assert((size_t)(index + 1) * TRAMPOLINE_SIZE <= state->trampolines.size); + + uint64_t value = (uintptr_t)symbols_map[ordinal]; + + /* Generate the trampoline + 0: 58000048 ldr x8, 8 + 4: d61f0100 br x8 + 8: 00000000 // The next two words contain the 64-bit address to jump to. + c: 00000000 + */ + p[0] = 0x58000048; + p[1] = 0xD61F0100; + p[2] = value & 0xffffffff; + p[3] = value >> 32; + + patch_aarch64_26r(location, (uintptr_t)p); +} + +static void +combine_symbol_mask(const symbol_mask src, symbol_mask dest) +{ + // Calculate the union of the trampolines required by each StencilGroup + for (size_t i = 0; i < SYMBOL_MASK_WORDS; i++) { + dest[i] |= src[i]; + } +} + // Compiles executor in-place. Don't forget to call _PyJIT_Free later! int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction trace[], size_t length) { const StencilGroup *group; // Loop once to find the total compiled size: - uintptr_t instruction_starts[UOP_MAX_TRACE_LENGTH]; size_t code_size = 0; size_t data_size = 0; + jit_state state = {}; group = &trampoline; code_size += group->code_size; data_size += group->data_size; for (size_t i = 0; i < length; i++) { const _PyUOpInstruction *instruction = &trace[i]; group = &stencil_groups[instruction->opcode]; - instruction_starts[i] = code_size; + state.instruction_starts[i] = code_size; code_size += group->code_size; data_size += group->data_size; + combine_symbol_mask(group->trampoline_mask, state.trampolines.mask); } group = &stencil_groups[_FATAL_ERROR]; code_size += group->code_size; data_size += group->data_size; + combine_symbol_mask(group->trampoline_mask, state.trampolines.mask); + // Calculate the size of the trampolines required by the whole trace + for (size_t i = 0; i < Py_ARRAY_LENGTH(state.trampolines.mask); i++) { + state.trampolines.size += _Py_popcount32(state.trampolines.mask[i]) * TRAMPOLINE_SIZE; + } // Round up to the nearest page: size_t page_size = get_page_size(); assert((page_size & (page_size - 1)) == 0); - size_t padding = page_size - ((code_size + data_size) & (page_size - 1)); - size_t total_size = code_size + data_size + padding; + size_t padding = page_size - ((code_size + data_size + state.trampolines.size) & (page_size - 1)); + size_t total_size = code_size + data_size + state.trampolines.size + padding; unsigned char *memory = jit_alloc(total_size); if (memory == NULL) { return -1; } // Update the offsets of each instruction: for (size_t i = 0; i < length; i++) { - instruction_starts[i] += (uintptr_t)memory; + state.instruction_starts[i] += (uintptr_t)memory; } // Loop again to emit the code: unsigned char *code = memory; unsigned char *data = memory + code_size; + state.trampolines.mem = memory + code_size + data_size; // Compile the trampoline, which handles converting between the native // calling convention and the calling convention used by jitted code // (which may be different for efficiency reasons). On platforms where // we don't change calling conventions, the trampoline is empty and // nothing is emitted here: group = &trampoline; - group->emit(code, data, executor, NULL, instruction_starts); + group->emit(code, data, executor, NULL, &state); code += group->code_size; data += group->data_size; assert(trace[0].opcode == _START_EXECUTOR); for (size_t i = 0; i < length; i++) { const _PyUOpInstruction *instruction = &trace[i]; group = &stencil_groups[instruction->opcode]; - group->emit(code, data, executor, instruction, instruction_starts); + group->emit(code, data, executor, instruction, &state); code += group->code_size; data += group->data_size; } // Protect against accidental buffer overrun into data: group = &stencil_groups[_FATAL_ERROR]; - group->emit(code, data, executor, NULL, instruction_starts); + group->emit(code, data, executor, NULL, &state); code += group->code_size; data += group->data_size; assert(code == memory + code_size); diff --git a/Python/marshal.c b/Python/marshal.c index b1708a7306f9e7..3d127b4e331d0d 100644 --- a/Python/marshal.c +++ b/Python/marshal.c @@ -76,6 +76,7 @@ module marshal #define TYPE_UNKNOWN '?' #define TYPE_SET '<' #define TYPE_FROZENSET '>' +#define TYPE_SLICE ':' #define FLAG_REF '\x80' /* with a type, add obj to index */ #define TYPE_ASCII 'a' @@ -613,6 +614,13 @@ w_complex_object(PyObject *v, char flag, WFILE *p) w_pstring(view.buf, view.len, p); PyBuffer_Release(&view); } + else if (PySlice_Check(v)) { + PySliceObject *slice = (PySliceObject *)v; + W_TYPE(TYPE_SLICE, p); + w_object(slice->start, p); + w_object(slice->stop, p); + w_object(slice->step, p); + } else { W_TYPE(TYPE_UNKNOWN, p); p->error = WFERR_UNMARSHALLABLE; @@ -1534,6 +1542,32 @@ r_object(RFILE *p) retval = Py_NewRef(v); break; + case TYPE_SLICE: + { + Py_ssize_t idx = r_ref_reserve(flag, p); + PyObject *stop = NULL; + PyObject *step = NULL; + PyObject *start = r_object(p); + if (start == NULL) { + goto cleanup; + } + stop = r_object(p); + if (stop == NULL) { + goto cleanup; + } + step = r_object(p); + if (step == NULL) { + goto cleanup; + } + retval = PySlice_New(start, stop, step); + r_ref_insert(retval, idx, flag, p); + cleanup: + Py_XDECREF(start); + Py_XDECREF(stop); + Py_XDECREF(step); + break; + } + default: /* Bogus data got written, which isn't ideal. This will let you keep working and recover. */ diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 49f01ca2932ee2..3fc9d3118d59ad 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -115,7 +115,7 @@ static void *opcode_targets[256] = { &&TARGET_UNPACK_EX, &&TARGET_UNPACK_SEQUENCE, &&TARGET_YIELD_VALUE, - &&TARGET__DO_CALL_FUNCTION_EX, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/optimizer.c b/Python/optimizer.c index 978649faa04d45..b876b6c2bd72fd 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -643,14 +643,12 @@ translate_bytecode_to_trace( int bitcount = _Py_popcount32(counter); int jump_likely = bitcount > 8; /* If bitcount is 8 (half the jumps were taken), adjust confidence by 50%. - If it's 16 or 0 (all or none were taken), adjust by 10% - (since the future is still somewhat uncertain). For values in between, adjust proportionally. */ if (jump_likely) { - confidence = confidence * (bitcount + 2) / 20; + confidence = confidence * bitcount / 16; } else { - confidence = confidence * (18 - bitcount) / 20; + confidence = confidence * (16 - bitcount) / 16; } uint32_t uopcode = BRANCH_TO_GUARD[opcode - POP_JUMP_IF_FALSE][jump_likely]; DPRINTF(2, "%d: %s(%d): counter=%04x, bitcount=%d, likely=%d, confidence=%d, uopcode=%s\n", diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index b202b58a8b7214..06826ff942a761 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -56,14 +56,14 @@ static int get_mutations(PyObject* dict) { assert(PyDict_CheckExact(dict)); PyDictObject *d = (PyDictObject *)dict; - return (d->ma_version_tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS)-1); + return (d->_ma_watcher_tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS)-1); } static void increment_mutations(PyObject* dict) { assert(PyDict_CheckExact(dict)); PyDictObject *d = (PyDictObject *)dict; - d->ma_version_tag += (1 << DICT_MAX_WATCHERS); + d->_ma_watcher_tag += (1 << DICT_MAX_WATCHERS); } /* The first two dict watcher IDs are reserved for CPython, @@ -385,6 +385,30 @@ get_code(_PyUOpInstruction *op) return co; } +static PyCodeObject * +get_code_with_logging(_PyUOpInstruction *op) +{ + PyCodeObject *co = NULL; + uint64_t push_operand = op->operand; + if (push_operand & 1) { + co = (PyCodeObject *)(push_operand & ~1); + DPRINTF(3, "code=%p ", co); + assert(PyCode_Check(co)); + } + else { + PyFunctionObject *func = (PyFunctionObject *)push_operand; + DPRINTF(3, "func=%p ", func); + if (func == NULL) { + DPRINTF(3, "\n"); + DPRINTF(1, "Missing function\n"); + return NULL; + } + co = (PyCodeObject *)func->func_code; + DPRINTF(3, "code=%p ", co); + } + return co; +} + /* 1 for success, 0 for not ready, cannot error at the moment. */ static int optimize_uops( diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 9a1b9da52f4bb5..c73b632d1afdd7 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -182,7 +182,9 @@ dummy_func(void) { res = sym_new_type(ctx, &PyFloat_Type); } } - res = sym_new_unknown(ctx); + else { + res = sym_new_unknown(ctx); + } } op(_BINARY_OP_ADD_INT, (left, right -- res)) { @@ -448,8 +450,10 @@ dummy_func(void) { top = bottom; } - op(_SWAP, (bottom, unused[oparg-2], top -- - top, unused[oparg-2], bottom)) { + op(_SWAP, (bottom_in, unused[oparg-2], top_in -- + top_out, unused[oparg-2], bottom_out)) { + bottom_out = bottom_in; + top_out = top_in; } op(_LOAD_ATTR_INSTANCE_VALUE, (offset/1, owner -- attr, null if (oparg & 1))) { @@ -479,9 +483,7 @@ dummy_func(void) { op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) { (void)owner; attr = sym_new_not_null(ctx); - if (oparg & 1) { - self_or_null = sym_new_unknown(ctx); - } + self_or_null = sym_new_unknown(ctx); } op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) { @@ -570,30 +572,17 @@ dummy_func(void) { op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) { int argcount = oparg; - (void)callable; PyCodeObject *co = NULL; assert((this_instr + 2)->opcode == _PUSH_FRAME); - uint64_t push_operand = (this_instr + 2)->operand; - if (push_operand & 1) { - co = (PyCodeObject *)(push_operand & ~1); - DPRINTF(3, "code=%p ", co); - assert(PyCode_Check(co)); - } - else { - PyFunctionObject *func = (PyFunctionObject *)push_operand; - DPRINTF(3, "func=%p ", func); - if (func == NULL) { - DPRINTF(3, "\n"); - DPRINTF(1, "Missing function\n"); - ctx->done = true; - break; - } - co = (PyCodeObject *)func->func_code; - DPRINTF(3, "code=%p ", co); + co = get_code_with_logging((this_instr + 2)); + if (co == NULL) { + ctx->done = true; + break; } + assert(self_or_null != NULL); assert(args != NULL); if (sym_is_not_null(self_or_null)) { @@ -619,12 +608,17 @@ dummy_func(void) { } op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) { - /* The _Py_UOpsAbstractFrame design assumes that we can copy arguments across directly */ - (void)callable; - (void)self_or_null; - (void)args; - new_frame = NULL; - ctx->done = true; + (void)(self_or_null); + (void)(callable); + PyCodeObject *co = NULL; + assert((this_instr + 2)->opcode == _PUSH_FRAME); + co = get_code_with_logging((this_instr + 2)); + if (co == NULL) { + ctx->done = true; + break; + } + + new_frame = frame_new(ctx, co, 0, NULL, 0); } op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- new_frame: _Py_UOpsAbstractFrame *)) { @@ -654,11 +648,10 @@ dummy_func(void) { } op(_RETURN_VALUE, (retval -- res)) { - SYNC_SP(); + SAVE_STACK(); ctx->frame->stack_pointer = stack_pointer; frame_pop(ctx); stack_pointer = ctx->frame->stack_pointer; - res = retval; /* Stack space handling */ assert(corresponding_check_stack == NULL); @@ -673,6 +666,8 @@ dummy_func(void) { // might be impossible, but bailing is still safe ctx->done = true; } + RELOAD_STACK(); + res = retval; } op(_RETURN_GENERATOR, ( -- res)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 4d172e3c762704..ae532fd27769ab 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -93,9 +93,9 @@ } case _END_SEND: { - _Py_UopsSymbol *value; - value = sym_new_not_null(ctx); - stack_pointer[-2] = value; + _Py_UopsSymbol *val; + val = sym_new_not_null(ctx); + stack_pointer[-2] = val; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -630,7 +630,6 @@ ctx->frame->stack_pointer = stack_pointer; frame_pop(ctx); stack_pointer = ctx->frame->stack_pointer; - res = retval; /* Stack space handling */ assert(corresponding_check_stack == NULL); assert(co != NULL); @@ -643,6 +642,7 @@ // might be impossible, but bailing is still safe ctx->done = true; } + res = retval; stack_pointer[0] = res; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -832,9 +832,7 @@ _Py_UopsSymbol **res; _Py_UopsSymbol *null = NULL; res = &stack_pointer[0]; - for (int _i = 1; --_i >= 0;) { - res[_i] = sym_new_not_null(ctx); - } + res[0] = sym_new_not_null(ctx); null = sym_new_null(ctx); if (oparg & 1) stack_pointer[1] = null; stack_pointer += 1 + (oparg & 1); @@ -1021,9 +1019,7 @@ owner = stack_pointer[-1]; (void)owner; attr = sym_new_not_null(ctx); - if (oparg & 1) { - self_or_null = sym_new_unknown(ctx); - } + self_or_null = sym_new_unknown(ctx); stack_pointer[-1] = attr; if (oparg & 1) stack_pointer[0] = self_or_null; stack_pointer += (oparg & 1); @@ -1114,11 +1110,17 @@ PyModuleObject *mod = (PyModuleObject *)sym_get_const(owner); assert(PyModule_CheckExact(mod)); PyObject *dict = mod->md_dict; + stack_pointer[-1] = attr; + if (oparg & 1) stack_pointer[0] = null; + stack_pointer += (oparg & 1); + assert(WITHIN_STACK_BOUNDS()); PyObject *res = convert_global_to_const(this_instr, dict); if (res != NULL) { this_instr[-1].opcode = _POP_TOP; attr = sym_new_const(ctx, res); } + stack_pointer += -(oparg & 1); + assert(WITHIN_STACK_BOUNDS()); } if (attr == NULL) { /* No conversion made. We don't know what `attr` is. */ @@ -1239,7 +1241,11 @@ res = sym_new_type(ctx, &PyBool_Type); } else { + stack_pointer += -2; + assert(WITHIN_STACK_BOUNDS()); res = _Py_uop_sym_new_not_null(ctx); + stack_pointer += 2; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer[-2] = res; stack_pointer += -1; @@ -1659,21 +1665,25 @@ /* _MONITOR_CALL is not a viable micro-op for tier 2 */ case _PY_FRAME_GENERAL: { - _Py_UopsSymbol **args; _Py_UopsSymbol *self_or_null; _Py_UopsSymbol *callable; _Py_UOpsAbstractFrame *new_frame; - args = &stack_pointer[-oparg]; self_or_null = stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - /* The _Py_UOpsAbstractFrame design assumes that we can copy arguments across directly */ - (void)callable; - (void)self_or_null; - (void)args; - new_frame = NULL; - ctx->done = true; - stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame; - stack_pointer += -1 - oparg; + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); + (void)(self_or_null); + (void)(callable); + PyCodeObject *co = NULL; + assert((this_instr + 2)->opcode == _PUSH_FRAME); + co = get_code_with_logging((this_instr + 2)); + if (co == NULL) { + ctx->done = true; + break; + } + new_frame = frame_new(ctx, co, 0, NULL, 0); + stack_pointer[0] = (_Py_UopsSymbol *)new_frame; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1687,14 +1697,12 @@ } case _EXPAND_METHOD: { - _Py_UopsSymbol *method; + _Py_UopsSymbol **method; _Py_UopsSymbol **self; + method = &stack_pointer[-2 - oparg]; self = &stack_pointer[-1 - oparg]; - method = sym_new_not_null(ctx); - for (int _i = 1; --_i >= 0;) { - self[_i] = sym_new_not_null(ctx); - } - stack_pointer[-2 - oparg] = method; + method[0] = sym_new_not_null(ctx); + self[0] = sym_new_not_null(ctx); break; } @@ -1771,23 +1779,12 @@ (void)callable; PyCodeObject *co = NULL; assert((this_instr + 2)->opcode == _PUSH_FRAME); - uint64_t push_operand = (this_instr + 2)->operand; - if (push_operand & 1) { - co = (PyCodeObject *)(push_operand & ~1); - DPRINTF(3, "code=%p ", co); - assert(PyCode_Check(co)); - } - else { - PyFunctionObject *func = (PyFunctionObject *)push_operand; - DPRINTF(3, "func=%p ", func); - if (func == NULL) { - DPRINTF(3, "\n"); - DPRINTF(1, "Missing function\n"); - ctx->done = true; - break; - } - co = (PyCodeObject *)func->func_code; - DPRINTF(3, "code=%p ", co); + stack_pointer += -2 - oparg; + assert(WITHIN_STACK_BOUNDS()); + co = get_code_with_logging((this_instr + 2)); + if (co == NULL) { + ctx->done = true; + break; } assert(self_or_null != NULL); assert(args != NULL); @@ -1801,8 +1798,8 @@ } else { new_frame = frame_new(ctx, co, 0, NULL, 0); } - stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame; - stack_pointer += -1 - oparg; + stack_pointer[0] = (_Py_UopsSymbol *)new_frame; + stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } @@ -1835,9 +1832,11 @@ if (first_valid_check_stack == NULL) { first_valid_check_stack = corresponding_check_stack; } - else if (corresponding_check_stack) { - // delete all but the first valid _CHECK_STACK_SPACE - corresponding_check_stack->opcode = _NOP; + else { + if (corresponding_check_stack) { + // delete all but the first valid _CHECK_STACK_SPACE + corresponding_check_stack->opcode = _NOP; + } } corresponding_check_stack = NULL; break; @@ -2015,6 +2014,24 @@ /* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */ + case _MAYBE_EXPAND_METHOD_KW: { + _Py_UopsSymbol **func; + _Py_UopsSymbol **maybe_self; + _Py_UopsSymbol **args; + _Py_UopsSymbol *kwnames_out; + func = &stack_pointer[-3 - oparg]; + maybe_self = &stack_pointer[-2 - oparg]; + args = &stack_pointer[-1 - oparg]; + func[0] = sym_new_not_null(ctx); + maybe_self[0] = sym_new_not_null(ctx); + for (int _i = oparg; --_i >= 0;) { + args[_i] = sym_new_not_null(ctx); + } + kwnames_out = sym_new_not_null(ctx); + stack_pointer[-1] = kwnames_out; + break; + } + /* _DO_CALL_KW is not a viable micro-op for tier 2 */ case _PY_FRAME_KW: { @@ -2048,17 +2065,12 @@ } case _EXPAND_METHOD_KW: { - _Py_UopsSymbol *method; + _Py_UopsSymbol **method; _Py_UopsSymbol **self; - _Py_UopsSymbol *kwnames; + method = &stack_pointer[-3 - oparg]; self = &stack_pointer[-2 - oparg]; - method = sym_new_not_null(ctx); - for (int _i = 1; --_i >= 0;) { - self[_i] = sym_new_not_null(ctx); - } - kwnames = sym_new_not_null(ctx); - stack_pointer[-3 - oparg] = method; - stack_pointer[-1] = kwnames; + method[0] = sym_new_not_null(ctx); + self[0] = sym_new_not_null(ctx); break; } @@ -2077,7 +2089,17 @@ /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ - /* __DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ + case _MAKE_CALLARGS_A_TUPLE: { + _Py_UopsSymbol *tuple; + _Py_UopsSymbol *kwargs_out = NULL; + tuple = sym_new_not_null(ctx); + kwargs_out = sym_new_not_null(ctx); + stack_pointer[-1 - (oparg & 1)] = tuple; + if (oparg & 1) stack_pointer[-(oparg & 1)] = kwargs_out; + break; + } + + /* _DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */ case _MAKE_FUNCTION: { _Py_UopsSymbol *func; @@ -2087,9 +2109,9 @@ } case _SET_FUNCTION_ATTRIBUTE: { - _Py_UopsSymbol *func_st; - func_st = sym_new_not_null(ctx); - stack_pointer[-2] = func_st; + _Py_UopsSymbol *func_out; + func_out = sym_new_not_null(ctx); + stack_pointer[-2] = func_out; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); break; @@ -2108,14 +2130,14 @@ assert(framesize > 0); assert(framesize <= curr_space); curr_space -= framesize; + stack_pointer[0] = res; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); co = get_code(this_instr); if (co == NULL) { // might be impossible, but bailing is still safe ctx->done = true; } - stack_pointer[0] = res; - stack_pointer += 1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -2184,7 +2206,9 @@ res = sym_new_type(ctx, &PyFloat_Type); } } - res = sym_new_unknown(ctx); + else { + res = sym_new_unknown(ctx); + } stack_pointer[-2] = res; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -2192,12 +2216,16 @@ } case _SWAP: { - _Py_UopsSymbol *top; - _Py_UopsSymbol *bottom; - top = stack_pointer[-1]; - bottom = stack_pointer[-2 - (oparg-2)]; - stack_pointer[-2 - (oparg-2)] = top; - stack_pointer[-1] = bottom; + _Py_UopsSymbol *top_in; + _Py_UopsSymbol *bottom_in; + _Py_UopsSymbol *top_out; + _Py_UopsSymbol *bottom_out; + top_in = stack_pointer[-1]; + bottom_in = stack_pointer[-2 - (oparg-2)]; + bottom_out = bottom_in; + top_out = top_in; + stack_pointer[-2 - (oparg-2)] = top_out; + stack_pointer[-1] = bottom_out; break; } @@ -2223,7 +2251,11 @@ if (sym_is_const(flag)) { PyObject *value = sym_get_const(flag); assert(value != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); eliminate_pop_guard(this_instr, value != Py_True); + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -2236,7 +2268,11 @@ if (sym_is_const(flag)) { PyObject *value = sym_get_const(flag); assert(value != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); eliminate_pop_guard(this_instr, value != Py_False); + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); } stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -2249,14 +2285,22 @@ if (sym_is_const(flag)) { PyObject *value = sym_get_const(flag); assert(value != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); eliminate_pop_guard(this_instr, !Py_IsNone(value)); } - else if (sym_has_type(flag)) { - assert(!sym_matches_type(flag, &_PyNone_Type)); - eliminate_pop_guard(this_instr, true); + else { + if (sym_has_type(flag)) { + assert(!sym_matches_type(flag, &_PyNone_Type)); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + eliminate_pop_guard(this_instr, true); + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } @@ -2266,14 +2310,22 @@ if (sym_is_const(flag)) { PyObject *value = sym_get_const(flag); assert(value != NULL); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); eliminate_pop_guard(this_instr, Py_IsNone(value)); } - else if (sym_has_type(flag)) { - assert(!sym_matches_type(flag, &_PyNone_Type)); - eliminate_pop_guard(this_instr, false); + else { + if (sym_has_type(flag)) { + assert(!sym_matches_type(flag, &_PyNone_Type)); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + eliminate_pop_guard(this_instr, false); + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); } - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); break; } diff --git a/Python/parking_lot.c b/Python/parking_lot.c index 841b1d71ea16cb..a7e9760e35d87a 100644 --- a/Python/parking_lot.c +++ b/Python/parking_lot.c @@ -102,7 +102,14 @@ _PySemaphore_PlatformWait(_PySemaphore *sema, PyTime_t timeout) millis = INFINITE; } else { - millis = (DWORD) (timeout / 1000000); + PyTime_t div = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_TIMEOUT); + // Prevent overflow with clamping the result + if ((PyTime_t)PY_DWORD_MAX < div) { + millis = PY_DWORD_MAX; + } + else { + millis = (DWORD) div; + } } wait = WaitForSingleObjectEx(sema->platform_sem, millis, FALSE); if (wait == WAIT_OBJECT_0) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 8aebbe5c405ffe..ebeee4f41d795d 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -28,7 +28,7 @@ #include "pycore_sliceobject.h" // _PySlice_Fini() #include "pycore_sysmodule.h" // _PySys_ClearAuditHooks() #include "pycore_traceback.h" // _Py_DumpTracebackThreads() -#include "pycore_typeid.h" // _PyType_FinalizeIdPool() +#include "pycore_uniqueid.h" // _PyType_FinalizeIdPool() #include "pycore_typeobject.h" // _PyTypes_InitTypes() #include "pycore_typevarobject.h" // _Py_clear_generic_types() #include "pycore_unicodeobject.h" // _PyUnicode_InitTypes() @@ -1834,7 +1834,7 @@ finalize_interp_types(PyInterpreterState *interp) _PyTypes_Fini(interp); #ifdef Py_GIL_DISABLED - _PyType_FinalizeIdPool(interp); + _PyObject_FinalizeUniqueIdPool(interp); #endif _PyCode_Fini(interp); @@ -2020,7 +2020,7 @@ _Py_Finalize(_PyRuntimeState *runtime) /* Ensure that remaining threads are detached */ _PyEval_StopTheWorldAll(runtime); - /* Remaining daemon threads will automatically exit + /* Remaining daemon threads will be trapped in PyThread_hang_thread when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ _PyInterpreterState_SetFinalizing(tstate->interp, tstate); _PyRuntimeState_SetFinalizing(runtime, tstate); diff --git a/Python/pystate.c b/Python/pystate.c index 6b85e5a64fefcf..45e79ade7b6035 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -20,7 +20,7 @@ #include "pycore_runtime_init.h" // _PyRuntimeState_INIT #include "pycore_sysmodule.h" // _PySys_Audit() #include "pycore_obmalloc.h" // _PyMem_obmalloc_state_on_heap() -#include "pycore_typeid.h" // _PyType_FinalizeThreadLocalRefcounts() +#include "pycore_uniqueid.h" // _PyType_FinalizeThreadLocalRefcounts() /* -------------------------------------------------------------------------- CAUTION @@ -654,6 +654,7 @@ init_interpreter(PyInterpreterState *interp, interp->monitoring_callables[t][e] = NULL; } + interp->monitoring_tool_versions[t] = 0; } interp->sys_profile_initialized = false; interp->sys_trace_initialized = false; @@ -1745,7 +1746,7 @@ PyThreadState_Clear(PyThreadState *tstate) // Merge our thread-local refcounts into the type's own refcount and // free our local refcount array. - _PyType_FinalizeThreadLocalRefcounts((_PyThreadStateImpl *)tstate); + _PyObject_FinalizePerThreadRefcounts((_PyThreadStateImpl *)tstate); // Remove ourself from the biased reference counting table of threads. _Py_brc_remove_thread(tstate); @@ -1805,7 +1806,7 @@ tstate_delete_common(PyThreadState *tstate, int release_gil) _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate; tstate->interp->object_state.reftotal += tstate_impl->reftotal; tstate_impl->reftotal = 0; - assert(tstate_impl->types.refcounts == NULL); + assert(tstate_impl->refcounts.values == NULL); #endif HEAD_UNLOCK(runtime); diff --git a/Python/specialize.c b/Python/specialize.c index d8bff39511cf12..4b33a468733d6b 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -1599,7 +1599,7 @@ function_get_version(PyObject *o, int opcode) assert(Py_IS_TYPE(o, &PyFunction_Type)); PyFunctionObject *func = (PyFunctionObject *)o; uint32_t version = _PyFunction_GetVersionForCurrentState(func); - if (version == 0) { + if (!_PyFunction_IsVersionValid(version)) { SPECIALIZATION_FAIL(opcode, SPEC_FAIL_OUT_OF_VERSIONS); return 0; } @@ -1692,7 +1692,7 @@ _Py_Specialize_BinarySubscr( goto fail; } uint32_t version = _PyFunction_GetVersionForCurrentState(func); - if (version == 0) { + if (!_PyFunction_IsVersionValid(version)) { SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS); goto fail; } @@ -1977,7 +1977,7 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, argcount = code->co_argcount; } int version = _PyFunction_GetVersionForCurrentState(func); - if (version == 0) { + if (!_PyFunction_IsVersionValid(version)) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS); return -1; } @@ -2009,7 +2009,7 @@ specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs, return -1; } int version = _PyFunction_GetVersionForCurrentState(func); - if (version == 0) { + if (!_PyFunction_IsVersionValid(version)) { SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS); return -1; } diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 425658131c2fce..3a01a7fe327c8f 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -291,6 +291,14 @@ PyThread_exit_thread(void) _endthreadex(0); } +void _Py_NO_RETURN +PyThread_hang_thread(void) +{ + while (1) { + SleepEx(INFINITE, TRUE); + } +} + /* * Lock support. It has to be implemented as semaphores. * I [Dag] tried to implement it with mutex but I could find a way to diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h index f588b4620da0d3..c010b3a827757f 100644 --- a/Python/thread_pthread.h +++ b/Python/thread_pthread.h @@ -16,6 +16,7 @@ #undef destructor #endif #include +#include /* pause(), also getthrid() on OpenBSD */ #if defined(__linux__) # include /* syscall(SYS_gettid) */ @@ -23,8 +24,6 @@ # include /* pthread_getthreadid_np() */ #elif defined(__FreeBSD_kernel__) # include /* syscall(SYS_thr_self) */ -#elif defined(__OpenBSD__) -# include /* getthrid() */ #elif defined(_AIX) # include /* thread_self() */ #elif defined(__NetBSD__) @@ -419,6 +418,18 @@ PyThread_exit_thread(void) #endif } +void _Py_NO_RETURN +PyThread_hang_thread(void) +{ + while (1) { +#if defined(__wasi__) + sleep(9999999); // WASI doesn't have pause() ?! +#else + pause(); +#endif + } +} + #ifdef USE_SEMAPHORES /* diff --git a/Python/typeid.c b/Python/uniqueid.c similarity index 51% rename from Python/typeid.c rename to Python/uniqueid.c index 83a68723ded61b..9a9ee2f39467b0 100644 --- a/Python/typeid.c +++ b/Python/uniqueid.c @@ -3,12 +3,14 @@ #include "pycore_lock.h" // PyMutex_LockFlags() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_object.h" // _Py_IncRefTotal -#include "pycore_typeid.h" +#include "pycore_uniqueid.h" -// This contains code for allocating unique ids to heap type objects -// and re-using those ids when the type is deallocated. +// This contains code for allocating unique ids for per-thread reference +// counting and re-using those ids when an object is deallocated. // -// See Include/internal/pycore_typeid.h for more details. +// Currently, per-thread reference counting is only used for heap types. +// +// See Include/internal/pycore_uniqueid.h for more details. #ifdef Py_GIL_DISABLED @@ -18,7 +20,7 @@ #define UNLOCK_POOL(pool) PyMutex_Unlock(&pool->mutex) static int -resize_interp_type_id_pool(struct _Py_type_id_pool *pool) +resize_interp_type_id_pool(struct _Py_unique_id_pool *pool) { if ((size_t)pool->size > PY_SSIZE_T_MAX / (2 * sizeof(*pool->table))) { return -1; @@ -29,8 +31,8 @@ resize_interp_type_id_pool(struct _Py_type_id_pool *pool) new_size = POOL_MIN_SIZE; } - _Py_type_id_entry *table = PyMem_Realloc(pool->table, - new_size * sizeof(*pool->table)); + _Py_unique_id_entry *table = PyMem_Realloc(pool->table, + new_size * sizeof(*pool->table)); if (table == NULL) { return -1; } @@ -50,70 +52,67 @@ resize_interp_type_id_pool(struct _Py_type_id_pool *pool) static int resize_local_refcounts(_PyThreadStateImpl *tstate) { - if (tstate->types.is_finalized) { + if (tstate->refcounts.is_finalized) { return -1; } - struct _Py_type_id_pool *pool = &tstate->base.interp->type_ids; + struct _Py_unique_id_pool *pool = &tstate->base.interp->unique_ids; Py_ssize_t size = _Py_atomic_load_ssize(&pool->size); - Py_ssize_t *refcnts = PyMem_Realloc(tstate->types.refcounts, + Py_ssize_t *refcnts = PyMem_Realloc(tstate->refcounts.values, size * sizeof(Py_ssize_t)); if (refcnts == NULL) { return -1; } - Py_ssize_t old_size = tstate->types.size; + Py_ssize_t old_size = tstate->refcounts.size; if (old_size < size) { memset(refcnts + old_size, 0, (size - old_size) * sizeof(Py_ssize_t)); } - tstate->types.refcounts = refcnts; - tstate->types.size = size; + tstate->refcounts.values = refcnts; + tstate->refcounts.size = size; return 0; } -void -_PyType_AssignId(PyHeapTypeObject *type) +Py_ssize_t +_PyObject_AssignUniqueId(PyObject *obj) { PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_type_id_pool *pool = &interp->type_ids; + struct _Py_unique_id_pool *pool = &interp->unique_ids; LOCK_POOL(pool); if (pool->freelist == NULL) { if (resize_interp_type_id_pool(pool) < 0) { - type->unique_id = -1; UNLOCK_POOL(pool); - return; + return -1; } } - _Py_type_id_entry *entry = pool->freelist; + _Py_unique_id_entry *entry = pool->freelist; pool->freelist = entry->next; - entry->type = type; - _PyObject_SetDeferredRefcount((PyObject *)type); - type->unique_id = (entry - pool->table); + entry->obj = obj; + _PyObject_SetDeferredRefcount(obj); + Py_ssize_t unique_id = (entry - pool->table); UNLOCK_POOL(pool); + return unique_id; } void -_PyType_ReleaseId(PyHeapTypeObject *type) +_PyObject_ReleaseUniqueId(Py_ssize_t unique_id) { PyInterpreterState *interp = _PyInterpreterState_GET(); - struct _Py_type_id_pool *pool = &interp->type_ids; + struct _Py_unique_id_pool *pool = &interp->unique_ids; - if (type->unique_id < 0) { - // The type doesn't have an id assigned. + if (unique_id < 0) { + // The id is not assigned return; } LOCK_POOL(pool); - _Py_type_id_entry *entry = &pool->table[type->unique_id]; - assert(entry->type == type); + _Py_unique_id_entry *entry = &pool->table[unique_id]; entry->next = pool->freelist; pool->freelist = entry; - - type->unique_id = -1; UNLOCK_POOL(pool); } @@ -127,8 +126,8 @@ _PyType_IncrefSlow(PyHeapTypeObject *type) return; } - assert(type->unique_id < tstate->types.size); - tstate->types.refcounts[type->unique_id]++; + assert(type->unique_id < tstate->refcounts.size); + tstate->refcounts.values[type->unique_id]++; #ifdef Py_REF_DEBUG _Py_IncRefTotal((PyThreadState *)tstate); #endif @@ -136,59 +135,64 @@ _PyType_IncrefSlow(PyHeapTypeObject *type) } void -_PyType_MergeThreadLocalRefcounts(_PyThreadStateImpl *tstate) +_PyObject_MergePerThreadRefcounts(_PyThreadStateImpl *tstate) { - if (tstate->types.refcounts == NULL) { + if (tstate->refcounts.values == NULL) { return; } - struct _Py_type_id_pool *pool = &tstate->base.interp->type_ids; + struct _Py_unique_id_pool *pool = &tstate->base.interp->unique_ids; LOCK_POOL(pool); - for (Py_ssize_t i = 0, n = tstate->types.size; i < n; i++) { - Py_ssize_t refcnt = tstate->types.refcounts[i]; + for (Py_ssize_t i = 0, n = tstate->refcounts.size; i < n; i++) { + Py_ssize_t refcnt = tstate->refcounts.values[i]; if (refcnt != 0) { - PyObject *type = (PyObject *)pool->table[i].type; - assert(PyType_Check(type)); - - _Py_atomic_add_ssize(&type->ob_ref_shared, + PyObject *obj = pool->table[i].obj; + _Py_atomic_add_ssize(&obj->ob_ref_shared, refcnt << _Py_REF_SHARED_SHIFT); - tstate->types.refcounts[i] = 0; + tstate->refcounts.values[i] = 0; } } UNLOCK_POOL(pool); } void -_PyType_FinalizeThreadLocalRefcounts(_PyThreadStateImpl *tstate) +_PyObject_FinalizePerThreadRefcounts(_PyThreadStateImpl *tstate) { - _PyType_MergeThreadLocalRefcounts(tstate); + _PyObject_MergePerThreadRefcounts(tstate); - PyMem_Free(tstate->types.refcounts); - tstate->types.refcounts = NULL; - tstate->types.size = 0; - tstate->types.is_finalized = 1; + PyMem_Free(tstate->refcounts.values); + tstate->refcounts.values = NULL; + tstate->refcounts.size = 0; + tstate->refcounts.is_finalized = 1; } void -_PyType_FinalizeIdPool(PyInterpreterState *interp) +_PyObject_FinalizeUniqueIdPool(PyInterpreterState *interp) { - struct _Py_type_id_pool *pool = &interp->type_ids; + struct _Py_unique_id_pool *pool = &interp->unique_ids; // First, set the free-list to NULL values while (pool->freelist) { - _Py_type_id_entry *next = pool->freelist->next; - pool->freelist->type = NULL; + _Py_unique_id_entry *next = pool->freelist->next; + pool->freelist->obj = NULL; pool->freelist = next; } // Now everything non-NULL is a type. Set the type's id to -1 in case it // outlives the interpreter. for (Py_ssize_t i = 0; i < pool->size; i++) { - PyHeapTypeObject *ht = pool->table[i].type; - if (ht) { - ht->unique_id = -1; - pool->table[i].type = NULL; + PyObject *obj = pool->table[i].obj; + pool->table[i].obj = NULL; + if (obj == NULL) { + continue; + } + if (PyType_Check(obj)) { + assert(PyType_HasFeature((PyTypeObject *)obj, Py_TPFLAGS_HEAPTYPE)); + ((PyHeapTypeObject *)obj)->unique_id = -1; + } + else { + Py_UNREACHABLE(); } } PyMem_Free(pool->table); diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index a0be2a0a203f8c..badd7b79102310 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -358,7 +358,6 @@ Modules/_testclinic.c - TestClass - ##----------------------- ## static types -Modules/_cursesmodule.c - PyCursesWindow_Type - Modules/_datetimemodule.c - PyDateTime_DateTimeType - Modules/_datetimemodule.c - PyDateTime_DateType - Modules/_datetimemodule.c - PyDateTime_DeltaType - @@ -383,7 +382,6 @@ Modules/_tkinter.c - Tktt_Type - Modules/xxlimited_35.c - Xxo_Type - ## exception types -Modules/_cursesmodule.c - PyCursesError - Modules/_tkinter.c - Tkinter_TclError - Modules/xxlimited_35.c - ErrorObject - Modules/xxmodule.c - ErrorObject - @@ -409,6 +407,7 @@ Modules/_tkinter.c - trbInCmd - Include/datetime.h - PyDateTimeAPI - Modules/_ctypes/cfield.c _ctypes_get_fielddesc initialized - Modules/_ctypes/malloc_closure.c - _pagesize - +Modules/_cursesmodule.c - curses_module_loaded - Modules/_cursesmodule.c - curses_initscr_called - Modules/_cursesmodule.c - curses_setupterm_called - Modules/_cursesmodule.c - curses_start_color_called - @@ -423,7 +422,6 @@ Modules/readline.c - libedit_history_start - Modules/_ctypes/cfield.c - formattable - Modules/_ctypes/malloc_closure.c - free_list - -Modules/_cursesmodule.c - curses_global_state - Modules/_curses_panel.c - lop - Modules/_ssl/debughelpers.c _PySSL_keylog_callback lock - Modules/_tkinter.c - quitMainLoop - diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index a4ce207703edcd..9c2981a68ac909 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -1,13 +1,13 @@ -from dataclasses import dataclass +from dataclasses import dataclass, field +import itertools import lexer import parser import re from typing import Optional - @dataclass class Properties: - escapes: bool + escaping_calls: dict[lexer.Token, tuple[lexer.Token, lexer.Token]] error_with_pop: bool error_without_pop: bool deopts: bool @@ -29,14 +29,21 @@ class Properties: needs_prev: bool = False def dump(self, indent: str) -> None: - print(indent, end="") - text = ", ".join([f"{key}: {value}" for (key, value) in self.__dict__.items()]) + simple_properties = self.__dict__.copy() + del simple_properties["escaping_calls"] + text = "escaping_calls:\n" + for tkns in self.escaping_calls.values(): + text += f"{indent} {tkns}\n" + text += ", ".join([f"{key}: {value}" for (key, value) in simple_properties.items()]) print(indent, text, sep="") @staticmethod def from_list(properties: list["Properties"]) -> "Properties": + escaping_calls: dict[lexer.Token, tuple[lexer.Token, lexer.Token]] = {} + for p in properties: + escaping_calls.update(p.escaping_calls) return Properties( - escapes=any(p.escapes for p in properties), + escaping_calls=escaping_calls, error_with_pop=any(p.error_with_pop for p in properties), error_without_pop=any(p.error_without_pop for p in properties), deopts=any(p.deopts for p in properties), @@ -59,9 +66,12 @@ def from_list(properties: list["Properties"]) -> "Properties": def infallible(self) -> bool: return not self.error_with_pop and not self.error_without_pop + @property + def escapes(self) -> bool: + return bool(self.escaping_calls) SKIP_PROPERTIES = Properties( - escapes=False, + escaping_calls={}, error_with_pop=False, error_without_pop=False, deopts=False, @@ -156,6 +166,7 @@ class Uop: stack: StackEffect caches: list[CacheEntry] deferred_refs: dict[lexer.Token, str | None] + output_stores: list[lexer.Token] body: list[lexer.Token] properties: Properties _size: int = -1 @@ -322,11 +333,24 @@ def analyze_stack( ] # Mark variables with matching names at the base of the stack as "peek" modified = False - for input, output in zip(inputs, outputs): - if input.name == output.name and not modified: - input.peek = output.peek = True + input_names: dict[str, lexer.Token] = { i.name : i.first_token for i in op.inputs if i.name != "unused" } + for input, output in itertools.zip_longest(inputs, outputs): + if output is None: + pass + elif input is None: + if output.name in input_names: + raise analysis_error( + f"Reuse of variable '{output.name}' at different stack location", + input_names[output.name]) + elif input.name == output.name: + if not modified: + input.peek = output.peek = True else: modified = True + if output.name in input_names: + raise analysis_error( + f"Reuse of variable '{output.name}' at different stack location", + input_names[output.name]) if isinstance(op, parser.InstDef): output_names = [out.name for out in outputs] for input in inputs: @@ -354,21 +378,46 @@ def analyze_caches(inputs: list[parser.InputEffect]) -> list[CacheEntry]: return [CacheEntry(i.name, int(i.size)) for i in caches] +def find_assignment_target(node: parser.InstDef, idx: int) -> list[lexer.Token]: + """Find the tokens that make up the left-hand side of an assignment""" + offset = 0 + for tkn in reversed(node.block.tokens[: idx]): + if tkn.kind in {"SEMI", "LBRACE", "RBRACE"}: + return node.block.tokens[idx - offset : idx] + offset += 1 + return [] + + +def find_stores_outputs(node: parser.InstDef) -> list[lexer.Token]: + res: list[lexer.Token] = [] + outnames = { out.name for out in node.outputs } + innames = { out.name for out in node.inputs } + for idx, tkn in enumerate(node.block.tokens): + if tkn.kind == "AND": + name = node.block.tokens[idx+1] + if name.text in outnames: + res.append(name) + if tkn.kind != "EQUALS": + continue + lhs = find_assignment_target(node, idx) + assert lhs + while lhs and lhs[0].kind == "COMMENT": + lhs = lhs[1:] + if len(lhs) != 1 or lhs[0].kind != "IDENTIFIER": + continue + name = lhs[0] + if name.text in innames: + raise analysis_error(f"Cannot assign to input variable '{name.text}'", name) + if name.text in outnames: + res.append(name) + return res + def analyze_deferred_refs(node: parser.InstDef) -> dict[lexer.Token, str | None]: """Look for PyStackRef_FromPyObjectNew() calls""" - def find_assignment_target(idx: int) -> list[lexer.Token]: - """Find the tokens that make up the left-hand side of an assignment""" - offset = 1 - for tkn in reversed(node.block.tokens[: idx - 1]): - if tkn.kind == "SEMI" or tkn.kind == "LBRACE" or tkn.kind == "RBRACE": - return node.block.tokens[idx - offset : idx - 1] - offset += 1 - return [] - def in_frame_push(idx: int) -> bool: for tkn in reversed(node.block.tokens[: idx - 1]): - if tkn.kind == "SEMI" or tkn.kind == "LBRACE" or tkn.kind == "RBRACE": + if tkn.kind in {"SEMI", "LBRACE", "RBRACE"}: return False if tkn.kind == "IDENTIFIER" and tkn.text == "_PyFrame_PushUnchecked": return True @@ -386,7 +435,7 @@ def in_frame_push(idx: int) -> bool: continue raise analysis_error("Expected '=' before PyStackRef_FromPyObjectNew", tkn) - lhs = find_assignment_target(idx) + lhs = find_assignment_target(node, idx - 1) if len(lhs) == 0: raise analysis_error( "PyStackRef_FromPyObjectNew() must be assigned to an output", tkn @@ -406,9 +455,13 @@ def in_frame_push(idx: int) -> bool: ) name = lhs[0].text - if not any(var.name == name for var in node.outputs): + match = ( + any(var.name == name for var in node.inputs) + or any(var.name == name for var in node.outputs) + ) + if not match: raise analysis_error( - f"PyStackRef_FromPyObjectNew() must be assigned to an output, not '{name}'", + f"PyStackRef_FromPyObjectNew() must be assigned to an input or output, not '{name}'", tkn, ) @@ -461,125 +514,203 @@ def has_error_without_pop(op: parser.InstDef) -> bool: NON_ESCAPING_FUNCTIONS = ( - "PyStackRef_FromPyObjectSteal", + "PyCFunction_GET_FLAGS", + "PyCFunction_GET_FUNCTION", + "PyCFunction_GET_SELF", + "PyCell_GetRef", + "PyCell_New", + "PyCell_SwapTakeRef", + "PyExceptionInstance_Class", + "PyException_GetCause", + "PyException_GetContext", + "PyException_GetTraceback", + "PyFloat_AS_DOUBLE", + "PyFloat_FromDouble", + "PyFunction_GET_CODE", + "PyFunction_GET_GLOBALS", + "PyList_GET_ITEM", + "PyList_GET_SIZE", + "PyList_SET_ITEM", + "PyLong_AsLong", + "PyLong_FromLong", + "PyLong_FromSsize_t", + "PySlice_New", "PyStackRef_AsPyObjectBorrow", + "PyStackRef_AsPyObjectNew", "PyStackRef_AsPyObjectSteal", + "PyStackRef_CLEAR", "PyStackRef_CLOSE", "PyStackRef_DUP", - "PyStackRef_CLEAR", + "PyStackRef_False", + "PyStackRef_FromPyObjectImmortal", + "PyStackRef_FromPyObjectNew", + "PyStackRef_FromPyObjectSteal", + "PyStackRef_Is", "PyStackRef_IsNull", + "PyStackRef_None", "PyStackRef_TYPE", - "PyStackRef_False", "PyStackRef_True", - "PyStackRef_None", - "PyStackRef_Is", - "PyStackRef_FromPyObjectNew", - "PyStackRef_AsPyObjectNew", - "PyStackRef_FromPyObjectImmortal", - "Py_INCREF", - "_PyManagedDictPointer_IsValues", - "_PyObject_GetManagedDict", - "_PyObject_ManagedDictPointer", - "_PyObject_InlineValues", - "_PyDictValues_AddToInsertionOrder", - "Py_DECREF", - "Py_XDECREF", - "_Py_DECREF_SPECIALIZED", - "DECREF_INPUTS_AND_REUSE_FLOAT", - "PyUnicode_Append", - "_PyLong_IsZero", - "Py_SIZE", - "Py_TYPE", - "PyList_GET_ITEM", - "PyList_SET_ITEM", "PyTuple_GET_ITEM", - "PyList_GET_SIZE", "PyTuple_GET_SIZE", + "PyType_HasFeature", + "PyUnicode_Append", + "PyUnicode_Concat", + "PyUnicode_GET_LENGTH", + "PyUnicode_READ_CHAR", "Py_ARRAY_LENGTH", + "Py_CLEAR", + "Py_DECREF", + "Py_FatalError", + "Py_INCREF", + "Py_IS_TYPE", + "Py_NewRef", + "Py_REFCNT", + "Py_SIZE", + "Py_TYPE", + "Py_UNREACHABLE", "Py_Unicode_GET_LENGTH", - "PyUnicode_READ_CHAR", - "_Py_SINGLETON", - "PyUnicode_GET_LENGTH", - "_PyLong_IsCompact", - "_PyLong_IsNonNegativeCompact", + "Py_XDECREF", + "_PyCode_CODE", + "_PyDictValues_AddToInsertionOrder", + "_PyErr_Occurred", + "_PyEval_FrameClearAndPop", + "_PyFrame_GetCode", + "_PyFrame_IsIncomplete", + "_PyFrame_PushUnchecked", + "_PyFrame_SetStackPointer", + "_PyFrame_StackPush", + "_PyFunction_SetVersion", + "_PyGen_GetGeneratorFromFrame", + "_PyInterpreterState_GET", + "_PyList_AppendTakeRef", + "_PyList_FromStackRefSteal", + "_PyList_ITEMS", + "_PyLong_Add", "_PyLong_CompactValue", "_PyLong_DigitCount", - "_Py_NewRef", - "_Py_IsImmortal", - "PyLong_FromLong", - "_Py_STR", - "_PyLong_Add", + "_PyLong_IsCompact", + "_PyLong_IsNonNegativeCompact", + "_PyLong_IsZero", "_PyLong_Multiply", "_PyLong_Subtract", - "Py_NewRef", - "_PyList_ITEMS", - "_PyTuple_ITEMS", - "_PyList_AppendTakeRef", - "_Py_atomic_load_uintptr_relaxed", - "_PyFrame_GetCode", + "_PyManagedDictPointer_IsValues", + "_PyObject_GC_IS_TRACKED", + "_PyObject_GC_MAY_BE_TRACKED", + "_PyObject_GC_TRACK", + "_PyObject_GetManagedDict", + "_PyObject_InlineValues", + "_PyObject_ManagedDictPointer", "_PyThreadState_HasStackSpace", - "_PyUnicode_Equal", - "_PyFrame_SetStackPointer", + "_PyTuple_FromArraySteal", + "_PyTuple_FromStackRefSteal", + "_PyTuple_ITEMS", "_PyType_HasFeature", - "PyUnicode_Concat", - "PySlice_New", + "_PyType_NewManagedObject", + "_PyUnicode_Equal", + "_PyUnicode_JoinArray", + "_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY", + "_Py_DECREF_NO_DEALLOC", + "_Py_DECREF_SPECIALIZED", + "_Py_EnterRecursiveCallTstateUnchecked", + "_Py_ID", + "_Py_IsImmortal", + "_Py_IsImmortalLoose", "_Py_LeaveRecursiveCallPy", - "CALL_STAT_INC", - "STAT_INC", + "_Py_LeaveRecursiveCallTstate", + "_Py_NewRef", + "_Py_SINGLETON", + "_Py_STR", + "_Py_atomic_load_uintptr_relaxed", + "_Py_set_eval_breaker_bit", + "advance_backoff_counter", + "assert", + "backoff_counter_triggers", + "initial_temperature_backoff_counter", "maybe_lltrace_resume_frame", - "_PyUnicode_JoinArray", - "_PyEval_FrameClearAndPop", - "_PyFrame_StackPush", - "PyCell_New", - "PyFloat_AS_DOUBLE", - "_PyFrame_PushUnchecked", - "Py_FatalError", - "STACKREFS_TO_PYOBJECTS", - "STACKREFS_TO_PYOBJECTS_CLEANUP", - "CONVERSION_FAILED", - "_PyList_FromStackRefSteal", - "_PyTuple_FromArraySteal", - "_PyTuple_FromStackRefSteal", - "_Py_set_eval_breaker_bit" + "restart_backoff_counter", ) -ESCAPING_FUNCTIONS = ( - "import_name", - "import_from", -) - - -def makes_escaping_api_call(instr: parser.InstDef) -> bool: - if "CALL_INTRINSIC" in instr.name: - return True - if instr.name == "_BINARY_OP": - return True - tkns = iter(instr.tokens) - for tkn in tkns: - if tkn.kind != lexer.IDENTIFIER: - continue +def find_stmt_start(node: parser.InstDef, idx: int) -> lexer.Token: + assert idx < len(node.block.tokens) + while True: + tkn = node.block.tokens[idx-1] + if tkn.kind in {"SEMI", "LBRACE", "RBRACE"}: + break + idx -= 1 + assert idx > 0 + while node.block.tokens[idx].kind == "COMMENT": + idx += 1 + return node.block.tokens[idx] + + +def find_stmt_end(node: parser.InstDef, idx: int) -> lexer.Token: + assert idx < len(node.block.tokens) + while True: + idx += 1 + tkn = node.block.tokens[idx] + if tkn.kind == "SEMI": + return node.block.tokens[idx+1] + +def check_escaping_calls(instr: parser.InstDef, escapes: dict[lexer.Token, tuple[lexer.Token, lexer.Token]]) -> None: + calls = {escapes[t][0] for t in escapes} + in_if = 0 + tkn_iter = iter(instr.block.tokens) + for tkn in tkn_iter: + if tkn.kind == "IF": + next(tkn_iter) + in_if = 1 + if tkn.kind == "IDENTIFIER" and tkn.text in ("DEOPT_IF", "ERROR_IF"): + next(tkn_iter) + in_if = 1 + elif tkn.kind == "LPAREN" and in_if: + in_if += 1 + elif tkn.kind == "RPAREN": + if in_if: + in_if -= 1 + elif tkn in calls and in_if: + raise analysis_error(f"Escaping call '{tkn.text} in condition", tkn) + +def find_escaping_api_calls(instr: parser.InstDef) -> dict[lexer.Token, tuple[lexer.Token, lexer.Token]]: + result: dict[lexer.Token, tuple[lexer.Token, lexer.Token]] = {} + tokens = instr.block.tokens + for idx, tkn in enumerate(tokens): try: - next_tkn = next(tkns) - except StopIteration: - return False + next_tkn = tokens[idx+1] + except IndexError: + break + if tkn.kind == "SWITCH": + raise analysis_error(f"switch statements are not supported due to their complex flow control. Sorry.", tkn) if next_tkn.kind != lexer.LPAREN: continue - if tkn.text in ESCAPING_FUNCTIONS: - return True - if tkn.text == "tp_vectorcall": - return True - if not tkn.text.startswith("Py") and not tkn.text.startswith("_Py"): - continue - if tkn.text.endswith("Check"): - continue - if tkn.text.startswith("Py_Is"): - continue - if tkn.text.endswith("CheckExact"): - continue - if tkn.text in NON_ESCAPING_FUNCTIONS: + if tkn.kind == lexer.IDENTIFIER: + if tkn.text.upper() == tkn.text: + # simple macro + continue + #if not tkn.text.startswith(("Py", "_Py", "monitor")): + # continue + if tkn.text.startswith(("sym_", "optimize_")): + # Optimize functions + continue + if tkn.text.endswith("Check"): + continue + if tkn.text.startswith("Py_Is"): + continue + if tkn.text.endswith("CheckExact"): + continue + if tkn.text in NON_ESCAPING_FUNCTIONS: + continue + elif tkn.kind == "RPAREN": + prev = tokens[idx-1] + if prev.text.endswith("_t") or prev.text == "*" or prev.text == "int": + #cast + continue + elif tkn.kind != "RBRACKET": continue - return True - return False + start = find_stmt_start(instr, idx) + end = find_stmt_end(instr, idx) + result[start] = tkn, end + check_escaping_calls(instr, result) + return result EXITS = { @@ -651,6 +782,7 @@ def effect_depends_on_oparg_1(op: parser.InstDef) -> bool: def compute_properties(op: parser.InstDef) -> Properties: + escaping_calls = find_escaping_api_calls(op) has_free = ( variable_used(op, "PyCell_New") or variable_used(op, "PyCell_GetRef") @@ -671,7 +803,7 @@ def compute_properties(op: parser.InstDef) -> Properties: error_with_pop = has_error_with_pop(op) error_without_pop = has_error_without_pop(op) return Properties( - escapes=makes_escaping_api_call(op), + escaping_calls=escaping_calls, error_with_pop=error_with_pop, error_without_pop=error_without_pop, deopts=deopts_if, @@ -706,6 +838,7 @@ def make_uop( stack=analyze_stack(op), caches=analyze_caches(inputs), deferred_refs=analyze_deferred_refs(op), + output_stores=find_stores_outputs(op), body=op.block.tokens, properties=compute_properties(op), ) @@ -726,6 +859,7 @@ def make_uop( stack=analyze_stack(op, bit), caches=analyze_caches(inputs), deferred_refs=analyze_deferred_refs(op), + output_stores=find_stores_outputs(op), body=op.block.tokens, properties=properties, ) @@ -749,6 +883,7 @@ def make_uop( stack=analyze_stack(op), caches=analyze_caches(inputs), deferred_refs=analyze_deferred_refs(op), + output_stores=find_stores_outputs(op), body=op.block.tokens, properties=properties, ) diff --git a/Tools/cases_generator/cwriter.py b/Tools/cases_generator/cwriter.py index 069f0177a74018..8cba9127fa3071 100644 --- a/Tools/cases_generator/cwriter.py +++ b/Tools/cases_generator/cwriter.py @@ -18,8 +18,9 @@ def __init__(self, out: TextIO, indent: int, line_directives: bool): def set_position(self, tkn: Token) -> None: if self.last_token is not None: - if self.last_token.line < tkn.line: + if self.last_token.end_line < tkn.line: self.out.write("\n") + if self.last_token.line < tkn.line: if self.line_directives: self.out.write(f'#line {tkn.line} "{tkn.filename}"\n') self.out.write(" " * self.indents[-1]) @@ -91,6 +92,8 @@ def emit_token(self, tkn: Token) -> None: self.maybe_dedent(tkn.text) self.set_position(tkn) self.emit_text(tkn.text) + if tkn.kind == "CMACRO": + self.newline = True self.maybe_indent(tkn.text) def emit_str(self, txt: str) -> None: diff --git a/Tools/cases_generator/generators_common.py b/Tools/cases_generator/generators_common.py index 4cfd4ad3d05988..0bfa1a3b56fbc2 100644 --- a/Tools/cases_generator/generators_common.py +++ b/Tools/cases_generator/generators_common.py @@ -9,18 +9,47 @@ analysis_error, ) from cwriter import CWriter -from typing import Callable, Mapping, TextIO, Iterator +from typing import Callable, Mapping, TextIO, Iterator, Iterable from lexer import Token -from stack import Stack +from stack import Stack, Local, Storage, StackError +# Set this to true for voluminous output showing state of stack and locals +PRINT_STACKS = False -ROOT = Path(__file__).parent.parent.parent -DEFAULT_INPUT = (ROOT / "Python/bytecodes.c").absolute().as_posix() +class TokenIterator: + + look_ahead: Token | None + iterator: Iterator[Token] + + def __init__(self, tkns: Iterable[Token]): + self.iterator = iter(tkns) + self.look_ahead = None + + def __iter__(self) -> "TokenIterator": + return self + + def __next__(self) -> Token: + if self.look_ahead is None: + return next(self.iterator) + else: + res = self.look_ahead + self.look_ahead = None + return res + + def peek(self) -> Token | None: + if self.look_ahead is None: + for tkn in self.iterator: + self.look_ahead = tkn + break + return self.look_ahead + +ROOT = Path(__file__).parent.parent.parent.resolve() +DEFAULT_INPUT = (ROOT / "Python/bytecodes.c").as_posix() def root_relative_path(filename: str) -> str: try: - return Path(filename).absolute().relative_to(ROOT).as_posix() + return Path(filename).resolve().relative_to(ROOT).as_posix() except ValueError: # Not relative to root, just return original path. return filename @@ -47,22 +76,28 @@ def write_header( ) -def emit_to(out: CWriter, tkn_iter: Iterator[Token], end: str) -> None: +def emit_to(out: CWriter, tkn_iter: TokenIterator, end: str) -> Token: parens = 0 for tkn in tkn_iter: if tkn.kind == end and parens == 0: - return + return tkn if tkn.kind == "LPAREN": parens += 1 if tkn.kind == "RPAREN": parens -= 1 out.emit(tkn) + raise analysis_error(f"Expecting {end}. Reached end of file", tkn) ReplacementFunctionType = Callable[ - [Token, Iterator[Token], Uop, Stack, Instruction | None], None + [Token, TokenIterator, Uop, Storage, Instruction | None], bool ] +def always_true(tkn: Token | None) -> bool: + if tkn is None: + return False + return tkn.text in {"true", "1"} + class Emitter: out: CWriter @@ -75,21 +110,41 @@ def __init__(self, out: CWriter): "ERROR_IF": self.error_if, "ERROR_NO_POP": self.error_no_pop, "DECREF_INPUTS": self.decref_inputs, + "DEAD": self.kill, + "INPUTS_DEAD": self.kill_inputs, "SYNC_SP": self.sync_sp, - "PyStackRef_FromPyObjectNew": self.py_stack_ref_from_py_object_new, + "SAVE_STACK": self.save_stack, + "RELOAD_STACK": self.reload_stack, + "PyStackRef_CLOSE": self.stackref_close, + "PyStackRef_AsPyObjectSteal": self.stackref_steal, + "DISPATCH": self.dispatch } self.out = out + def dispatch( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + ) -> bool: + self.emit(tkn) + return False + def deopt_if( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - unused: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: self.out.emit_at("DEOPT_IF", tkn) - self.out.emit(next(tkn_iter)) + lparen = next(tkn_iter) + self.emit(lparen) + assert lparen.kind == "LPAREN" + first_tkn = tkn_iter.peek() emit_to(self.out, tkn_iter, "RPAREN") next(tkn_iter) # Semi colon self.out.emit(", ") @@ -97,25 +152,30 @@ def deopt_if( assert inst.family is not None self.out.emit(inst.family.name) self.out.emit(");\n") + return not always_true(first_tkn) exit_if = deopt_if def error_if( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: self.out.emit_at("if ", tkn) - self.out.emit(next(tkn_iter)) + lparen = next(tkn_iter) + self.emit(lparen) + assert lparen.kind == "LPAREN" + first_tkn = tkn_iter.peek() emit_to(self.out, tkn_iter, "COMMA") label = next(tkn_iter).text next(tkn_iter) # RPAREN next(tkn_iter) # Semi colon self.out.emit(") ") - c_offset = stack.peek_offset() + storage.clear_inputs("at ERROR_IF") + c_offset = storage.stack.peek_offset() try: offset = -int(c_offset) except ValueError: @@ -130,33 +190,35 @@ def error_if( self.out.emit(";\n") else: self.out.emit("{\n") - stack.flush_locally(self.out) + storage.copy().flush(self.out) self.out.emit("goto ") self.out.emit(label) self.out.emit(";\n") self.out.emit("}\n") + return not always_true(first_tkn) def error_no_pop( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: next(tkn_iter) # LPAREN next(tkn_iter) # RPAREN next(tkn_iter) # Semi colon self.out.emit_at("goto error;", tkn) + return False def decref_inputs( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: next(tkn_iter) next(tkn_iter) next(tkn_iter) @@ -178,59 +240,278 @@ def decref_inputs( self.out.emit(f"PyStackRef_XCLOSE({var.name});\n") else: self.out.emit(f"PyStackRef_CLOSE({var.name});\n") + for input in storage.inputs: + input.defined = False + return True + + def kill_inputs( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + ) -> bool: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + for var in storage.inputs: + var.defined = False + return True + + def kill( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + ) -> bool: + next(tkn_iter) + name_tkn = next(tkn_iter) + name = name_tkn.text + next(tkn_iter) + next(tkn_iter) + for var in storage.inputs: + if var.name == name: + var.defined = False + break + else: + raise analysis_error(f"'{name}' is not a live input-only variable", name_tkn) + return True + + def stackref_close( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + ) -> bool: + self.out.emit(tkn) + tkn = next(tkn_iter) + assert tkn.kind == "LPAREN" + self.out.emit(tkn) + name = next(tkn_iter) + self.out.emit(name) + if name.kind == "IDENTIFIER": + for var in storage.inputs: + if var.name == name.text: + var.defined = False + rparen = emit_to(self.out, tkn_iter, "RPAREN") + self.emit(rparen) + return True + + stackref_steal = stackref_close def sync_sp( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: next(tkn_iter) next(tkn_iter) next(tkn_iter) - stack.flush(self.out) + storage.clear_inputs("when syncing stack") + storage.flush(self.out) + self._print_storage(storage) + return True + + def emit_save(self, storage: Storage) -> None: + storage.save(self.out) + self._print_storage(storage) - def py_stack_ref_from_py_object_new( + def save_stack( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: - target = uop.deferred_refs[tkn] - if target is None: - # An assignment we don't handle, such as to a pointer or array. - self.out.emit(tkn) - return + ) -> bool: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + self.emit_save(storage) + return True + + def emit_reload(self, storage: Storage) -> None: + storage.reload(self.out) + self._print_storage(storage) + + def reload_stack( + self, + tkn: Token, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + ) -> bool: + next(tkn_iter) + next(tkn_iter) + next(tkn_iter) + self.emit_reload(storage) + return True + def _print_storage(self, storage: Storage) -> None: + if PRINT_STACKS: + self.out.start_line() + self.emit(storage.as_comment()) + self.out.start_line() + + def _emit_if( + self, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + ) -> tuple[bool, Token, Storage]: + """Returns (reachable?, closing '}', stack).""" + tkn = next(tkn_iter) + assert tkn.kind == "LPAREN" self.out.emit(tkn) - emit_to(self.out, tkn_iter, "SEMI") - self.out.emit(";\n") + rparen = emit_to(self.out, tkn_iter, "RPAREN") + self.emit(rparen) + if_storage = storage.copy() + reachable, rbrace, if_storage = self._emit_block(tkn_iter, uop, if_storage, inst, True) + try: + maybe_else = tkn_iter.peek() + if maybe_else and maybe_else.kind == "ELSE": + self._print_storage(storage) + self.emit(rbrace) + self.emit(next(tkn_iter)) + maybe_if = tkn_iter.peek() + if maybe_if and maybe_if.kind == "IF": + #Emit extra braces around the if to get scoping right + self.emit(" {\n") + self.emit(next(tkn_iter)) + else_reachable, rbrace, else_storage = self._emit_if(tkn_iter, uop, storage, inst) + self.out.start_line() + self.emit("}\n") + else: + else_reachable, rbrace, else_storage = self._emit_block(tkn_iter, uop, storage, inst, True) + if not reachable: + # Discard the if storage + reachable = else_reachable + storage = else_storage + elif not else_reachable: + # Discard the else storage + storage = if_storage + reachable = True + else: + if PRINT_STACKS: + self.emit("/* Merge */\n") + else_storage.merge(if_storage, self.out) + storage = else_storage + self._print_storage(storage) + else: + if reachable: + if PRINT_STACKS: + self.emit("/* Merge */\n") + if_storage.merge(storage, self.out) + storage = if_storage + self._print_storage(storage) + else: + # Discard the if storage + reachable = True + except StackError as ex: + self._print_storage(if_storage) + raise analysis_error(ex.args[0], rbrace) # from None + return reachable, rbrace, storage + + def _emit_block( + self, + tkn_iter: TokenIterator, + uop: Uop, + storage: Storage, + inst: Instruction | None, + emit_first_brace: bool + ) -> tuple[bool, Token, Storage]: + """ Returns (reachable?, closing '}', stack).""" + braces = 1 + out_stores = set(uop.output_stores) + tkn = next(tkn_iter) + reload: Token | None = None + try: + reachable = True + line : int = -1 + if tkn.kind != "LBRACE": + raise analysis_error(f"PEP 7: expected '{{', found: {tkn.text}", tkn) + escaping_calls = uop.properties.escaping_calls + if emit_first_brace: + self.emit(tkn) + self._print_storage(storage) + for tkn in tkn_iter: + if PRINT_STACKS and tkn.line != line: + self.out.start_line() + self.emit(storage.as_comment()) + self.out.start_line() + line = tkn.line + if tkn in escaping_calls: + if tkn != reload: + self.emit_save(storage) + _, reload = escaping_calls[tkn] + elif tkn == reload: + self.emit_reload(storage) + if tkn.kind == "LBRACE": + self.out.emit(tkn) + braces += 1 + elif tkn.kind == "RBRACE": + self._print_storage(storage) + braces -= 1 + if braces == 0: + return reachable, tkn, storage + self.out.emit(tkn) + elif tkn.kind == "GOTO": + reachable = False; + self.out.emit(tkn) + elif tkn.kind == "IDENTIFIER": + if tkn.text in self._replacers: + if not self._replacers[tkn.text](tkn, tkn_iter, uop, storage, inst): + reachable = False + else: + if tkn in out_stores: + for out in storage.outputs: + if out.name == tkn.text: + out.defined = True + out.in_memory = False + break + if tkn.text.startswith("DISPATCH"): + self._print_storage(storage) + reachable = False + self.out.emit(tkn) + elif tkn.kind == "IF": + self.out.emit(tkn) + if_reachable, rbrace, storage = self._emit_if(tkn_iter, uop, storage, inst) + if reachable: + reachable = if_reachable + self.out.emit(rbrace) + else: + self.out.emit(tkn) + except StackError as ex: + raise analysis_error(ex.args[0], tkn) from None + raise analysis_error("Expecting closing brace. Reached end of file", tkn) - # Flush the assignment to the stack. Note that we don't flush the - # stack pointer here, and instead are currently relying on initializing - # unused portions of the stack to NULL. - stack.flush_single_var(self.out, target, uop.stack.outputs) def emit_tokens( self, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: - tkns = uop.body[1:-1] - if not tkns: - return - tkn_iter = iter(tkns) + ) -> Storage: + tkn_iter = TokenIterator(uop.body) self.out.start_line() - for tkn in tkn_iter: - if tkn.kind == "IDENTIFIER" and tkn.text in self._replacers: - self._replacers[tkn.text](tkn, tkn_iter, uop, stack, inst) - else: - self.out.emit(tkn) + _, rbrace, storage = self._emit_block(tkn_iter, uop, storage, inst, False) + try: + self._print_storage(storage) + storage.push_outputs() + self._print_storage(storage) + except StackError as ex: + raise analysis_error(ex.args[0], rbrace) + return storage def emit(self, txt: str | Token) -> None: self.out.emit(txt) diff --git a/Tools/cases_generator/lexer.py b/Tools/cases_generator/lexer.py index d5831593215f76..37f96398ff175f 100644 --- a/Tools/cases_generator/lexer.py +++ b/Tools/cases_generator/lexer.py @@ -79,7 +79,7 @@ def choice(*opts: str) -> str: opmap = {pattern.replace("\\", "") or "\\": op for op, pattern in operators.items()} # Macros -macro = r"# *(ifdef|ifndef|undef|define|error|endif|if|else|include|#)" +macro = r"#.*\n" CMACRO = "CMACRO" id_re = r"[a-zA-Z_][0-9a-zA-Z_]*" @@ -333,6 +333,9 @@ def tokenize(src: str, line: int = 1, filename: str = "") -> Iterator[Token]: line += newlines else: begin = line, start - linestart + if kind == CMACRO: + linestart = end + line += 1 if kind != "\n": yield Token( filename, kind, text, begin, (line, start - linestart + len(text)) diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py index b74f627235ad84..7a1dfe1b85bf1a 100644 --- a/Tools/cases_generator/optimizer_generator.py +++ b/Tools/cases_generator/optimizer_generator.py @@ -18,11 +18,12 @@ ROOT, write_header, Emitter, + TokenIterator, ) from cwriter import CWriter from typing import TextIO, Iterator from lexer import Token -from stack import Local, Stack, StackError +from stack import Local, Stack, StackError, Storage DEFAULT_OUTPUT = ROOT / "Python/optimizer_cases.c.h" DEFAULT_ABSTRACT_INPUT = (ROOT / "Python/optimizer_bytecodes.c").absolute().as_posix() @@ -45,7 +46,7 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None: variables = {"unused"} if not skip_inputs: for var in reversed(uop.stack.inputs): - if var.name not in variables: + if var.used and var.name not in variables: variables.add(var.name) if var.condition: out.emit(f"{type_name(var)}{var.name} = NULL;\n") @@ -65,7 +66,7 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None: def decref_inputs( out: CWriter, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, stack: Stack, inst: Instruction | None, @@ -76,13 +77,27 @@ def decref_inputs( out.emit_at("", tkn) -def emit_default(out: CWriter, uop: Uop) -> None: - for i, var in enumerate(uop.stack.outputs): +def emit_default(out: CWriter, uop: Uop, stack: Stack) -> None: + for var in reversed(uop.stack.inputs): + stack.pop(var) + top_offset = stack.top_offset.copy() + for var in uop.stack.outputs: + if var.is_array() and not var.peek and not var.name == "unused": + c_offset = top_offset.to_c() + out.emit(f"{var.name} = &stack_pointer[{c_offset}];\n") + top_offset.push(var) + for var in uop.stack.outputs: + local = Local.undefined(var) + stack.push(local) if var.name != "unused" and not var.peek: + local.defined = True if var.is_array(): - out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") - out.emit(f"{var.name}[_i] = sym_new_not_null(ctx);\n") - out.emit("}\n") + if var.size == "1": + out.emit(f"{var.name}[0] = sym_new_not_null(ctx);\n") + else: + out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n") + out.emit(f"{var.name}[_i] = sym_new_not_null(ctx);\n") + out.emit("}\n") elif var.name == "null": out.emit(f"{var.name} = sym_new_null(ctx);\n") else: @@ -90,7 +105,12 @@ def emit_default(out: CWriter, uop: Uop) -> None: class OptimizerEmitter(Emitter): - pass + + def emit_save(self, storage: Storage) -> None: + storage.flush(self.out) + + def emit_reload(self, storage: Storage) -> None: + pass def write_uop( @@ -102,22 +122,18 @@ def write_uop( skip_inputs: bool, ) -> None: locals: dict[str, Local] = {} + prototype = override if override else uop try: - prototype = override if override else uop - is_override = override is not None out.start_line() - for var in reversed(prototype.stack.inputs): - code, local = stack.pop(var, extract_bits=True) - if not skip_inputs: + if override: + code_list, storage = Storage.for_uop(stack, prototype, extract_bits=False) + for code in code_list: out.emit(code) - if local.defined: - locals[local.name] = local - out.emit(stack.define_output_arrays(prototype.stack.outputs)) if debug: args = [] - for var in prototype.stack.inputs: - if not var.peek or is_override: - args.append(var.name) + for input in prototype.stack.inputs: + if not input.peek or override: + args.append(input.name) out.emit(f'DEBUG_PRINTF({", ".join(args)});\n') if override: for cache in uop.caches: @@ -130,20 +146,18 @@ def write_uop( out.emit(f"{type}{cache.name} = ({cast})this_instr->operand;\n") if override: emitter = OptimizerEmitter(out) - emitter.emit_tokens(override, stack, None) + # No reference management of inputs needed. + for var in storage.inputs: # type: ignore[possibly-undefined] + var.defined = False + storage = emitter.emit_tokens(override, storage, None) + out.start_line() + storage.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=False) else: - emit_default(out, uop) - - for var in prototype.stack.outputs: - if var.name in locals: - local = locals[var.name] - else: - local = Local.local(var) - stack.push(local) - out.start_line() - stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=True) + emit_default(out, uop, stack) + out.start_line() + stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=False) except StackError as ex: - raise analysis_error(ex.args[0], uop.body[0]) + raise analysis_error(ex.args[0], prototype.body[0]) # from None SKIPS = ("_EXTENDED_ARG",) diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py index de4d900563ee0b..a954bed4df073c 100644 --- a/Tools/cases_generator/stack.py +++ b/Tools/cases_generator/stack.py @@ -46,20 +46,41 @@ class Local: in_memory: bool defined: bool + def __repr__(self) -> str: + return f"Local('{self.item.name}', mem={self.in_memory}, defined={self.defined}, array={self.is_array()})" + + def compact_str(self) -> str: + mtag = "M" if self.in_memory else "" + dtag = "D" if self.defined else "" + atag = "A" if self.is_array() else "" + return f"'{self.item.name}'{mtag}{dtag}{atag}" + @staticmethod def unused(defn: StackItem) -> "Local": return Local(defn, False, defn.is_array(), False) @staticmethod - def local(defn: StackItem) -> "Local": + def undefined(defn: StackItem) -> "Local": array = defn.is_array() - return Local(defn, not array, array, True) + return Local(defn, not array, array, False) @staticmethod def redefinition(var: StackItem, prev: "Local") -> "Local": assert var.is_array() == prev.is_array() return Local(var, prev.cached, prev.in_memory, True) + @staticmethod + def from_memory(defn: StackItem) -> "Local": + return Local(defn, True, True, True) + + def copy(self) -> "Local": + return Local( + self.item, + self.cached, + self.in_memory, + self.defined + ) + @property def size(self) -> str: return self.item.size @@ -75,6 +96,16 @@ def condition(self) -> str | None: def is_array(self) -> bool: return self.item.is_array() + def __eq__(self, other: object) -> bool: + if not isinstance(other, Local): + return NotImplemented + return ( + self.item is other.item + and self.cached is other.cached + and self.in_memory is other.in_memory + and self.defined is other.defined + ) + @dataclass class StackOffset: @@ -156,10 +187,34 @@ def to_c(self) -> str: res = "-" + res[3:] return res + def as_int(self) -> int | None: + self.simplify() + int_offset = 0 + for item in self.popped: + try: + int_offset -= int(item) + except ValueError: + return None + for item in self.pushed: + try: + int_offset += int(item) + except ValueError: + return None + return int_offset + def clear(self) -> None: self.popped = [] self.pushed = [] + def __bool__(self) -> bool: + self.simplify() + return bool(self.popped) or bool(self.pushed) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, StackOffset): + return NotImplemented + return self.to_c() == other.to_c() + class StackError(Exception): pass @@ -174,7 +229,7 @@ def __init__(self) -> None: self.variables: list[Local] = [] self.defined: set[str] = set() - def pop(self, var: StackItem, extract_bits: bool = False) -> tuple[str, Local]: + def pop(self, var: StackItem, extract_bits: bool = True) -> tuple[str, Local]: self.top_offset.pop(var) indirect = "&" if var.is_array() else "" if self.variables: @@ -192,7 +247,7 @@ def pop(self, var: StackItem, extract_bits: bool = False) -> tuple[str, Local]: if var.name in UNUSED: if popped.name not in UNUSED and popped.name in self.defined: raise StackError( - f"Value is declared unused, but is already cached by prior operation" + f"Value is declared unused, but is already cached by prior operation as '{popped.name}'" ) return "", popped if not var.used: @@ -208,6 +263,7 @@ def pop(self, var: StackItem, extract_bits: bool = False) -> tuple[str, Local]: defn = f"{var.name} = &stack_pointer[{self.top_offset.to_c()}];\n" else: defn = f"{var.name} = stack_pointer[{self.top_offset.to_c()}];\n" + popped.in_memory = True return defn, Local.redefinition(var, popped) self.base_offset.pop(var) @@ -215,7 +271,7 @@ def pop(self, var: StackItem, extract_bits: bool = False) -> tuple[str, Local]: return "", Local.unused(var) self.defined.add(var.name) cast = f"({var.type})" if (not indirect and var.type) else "" - bits = ".bits" if cast and not extract_bits else "" + bits = ".bits" if cast and extract_bits else "" assign = f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}]{bits};" if var.condition: if var.condition == "1": @@ -226,27 +282,14 @@ def pop(self, var: StackItem, extract_bits: bool = False) -> tuple[str, Local]: assign = f"if ({var.condition}) {{ {assign} }}\n" else: assign = f"{assign}\n" - in_memory = var.is_array() or var.peek - return assign, Local(var, not var.is_array(), in_memory, True) + return assign, Local.from_memory(var) def push(self, var: Local) -> None: + assert(var not in self.variables) self.variables.append(var) self.top_offset.push(var.item) if var.item.used: self.defined.add(var.name) - var.defined = True - - def define_output_arrays(self, outputs: list[StackItem]) -> str: - res = [] - top_offset = self.top_offset.copy() - for var in outputs: - if var.is_array() and var.used and not var.peek: - c_offset = top_offset.to_c() - top_offset.push(var) - res.append(f"{var.name} = &stack_pointer[{c_offset}];\n") - else: - top_offset.push(var) - return "\n".join(res) @staticmethod def _do_emit( @@ -254,102 +297,92 @@ def _do_emit( var: StackItem, base_offset: StackOffset, cast_type: str = "uintptr_t", - extract_bits: bool = False, + extract_bits: bool = True, ) -> None: cast = f"({cast_type})" if var.type else "" - bits = ".bits" if cast and not extract_bits else "" + bits = ".bits" if cast and extract_bits else "" if var.condition == "0": return if var.condition and var.condition != "1": out.emit(f"if ({var.condition}) ") out.emit(f"stack_pointer[{base_offset.to_c()}]{bits} = {cast}{var.name};\n") - @staticmethod - def _do_flush( - out: CWriter, - variables: list[Local], - base_offset: StackOffset, - top_offset: StackOffset, - cast_type: str = "uintptr_t", - extract_bits: bool = False, - ) -> None: - out.start_line() - for var in variables: - if ( - var.cached - and not var.in_memory - and not var.item.peek - and not var.name in UNUSED - ): - Stack._do_emit(out, var.item, base_offset, cast_type, extract_bits) - base_offset.push(var.item) - if base_offset.to_c() != top_offset.to_c(): - print("base", base_offset, "top", top_offset) - assert False - number = base_offset.to_c() + def _adjust_stack_pointer(self, out: CWriter, number: str) -> None: if number != "0": + out.start_line() out.emit(f"stack_pointer += {number};\n") out.emit("assert(WITHIN_STACK_BOUNDS());\n") - out.start_line() - - def flush_locally( - self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool = False - ) -> None: - self._do_flush( - out, - self.variables[:], - self.base_offset.copy(), - self.top_offset.copy(), - cast_type, - extract_bits, - ) def flush( - self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool = False + self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool = True ) -> None: - self._do_flush( - out, - self.variables, - self.base_offset, - self.top_offset, - cast_type, - extract_bits, - ) - self.variables = [] - self.base_offset.clear() + out.start_line() + var_offset = self.base_offset.copy() + for var in self.variables: + if ( + var.defined and + not var.in_memory + ): + Stack._do_emit(out, var.item, var_offset, cast_type, extract_bits) + var.in_memory = True + var_offset.push(var.item) + number = self.top_offset.to_c() + self._adjust_stack_pointer(out, number) + self.base_offset -= self.top_offset self.top_offset.clear() + out.start_line() - def flush_single_var( - self, - out: CWriter, - var_name: str, - outputs: list[StackItem], - cast_type: str = "uintptr_t", - extract_bits: bool = False, - ) -> None: - assert any(var.name == var_name for var in outputs) - base_offset = self.base_offset.copy() - top_offset = self.top_offset.copy() - for var in self.variables: - base_offset.push(var.item) - for output in outputs: - if any(output == v.item for v in self.variables): - # The variable is already on the stack, such as a peeked value - # in the tier1 generator - continue - if output.name == var_name: - Stack._do_emit(out, output, base_offset, cast_type, extract_bits) - base_offset.push(output) - top_offset.push(output) - if base_offset.to_c() != top_offset.to_c(): - print("base", base_offset, "top", top_offset) - assert False + def is_flushed(self) -> bool: + return not self.variables and not self.base_offset and not self.top_offset def peek_offset(self) -> str: return self.top_offset.to_c() def as_comment(self) -> str: - return f"/* Variables: {[v.name for v in self.variables]}. Base offset: {self.base_offset.to_c()}. Top offset: {self.top_offset.to_c()} */" + variables = ", ".join([v.compact_str() for v in self.variables]) + return ( + f"/* Variables: {variables}. base: {self.base_offset.to_c()}. top: {self.top_offset.to_c()} */" + ) + + def copy(self) -> "Stack": + other = Stack() + other.top_offset = self.top_offset.copy() + other.base_offset = self.base_offset.copy() + other.variables = [var.copy() for var in self.variables] + other.defined = set(self.defined) + return other + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Stack): + return NotImplemented + return ( + self.top_offset == other.top_offset + and self.base_offset == other.base_offset + and self.variables == other.variables + ) + + def align(self, other: "Stack", out: CWriter) -> None: + if len(self.variables) != len(other.variables): + raise StackError("Cannot align stacks: differing variables") + if self.top_offset == other.top_offset: + return + diff = self.top_offset - other.top_offset + try: + self.top_offset -= diff + self.base_offset -= diff + self._adjust_stack_pointer(out, diff.to_c()) + except ValueError: + raise StackError("Cannot align stacks: cannot adjust stack pointer") + + def merge(self, other: "Stack", out: CWriter) -> None: + if len(self.variables) != len(other.variables): + raise StackError("Cannot merge stacks: differing variables") + for self_var, other_var in zip(self.variables, other.variables): + if self_var.name != other_var.name: + raise StackError(f"Mismatched variables on stack: {self_var.name} and {other_var.name}") + self_var.defined = self_var.defined and other_var.defined + self_var.in_memory = self_var.in_memory and other_var.in_memory + self.align(other, out) def get_stack_effect(inst: Instruction | PseudoInstruction) -> Stack: @@ -377,3 +410,213 @@ def stacks(inst: Instruction | PseudoInstruction) -> Iterator[StackEffect]: local = Local.unused(var) stack.push(local) return stack + +@dataclass +class Storage: + + stack: Stack + inputs: list[Local] + outputs: list[Local] + peeks: list[Local] + spilled: int = 0 + + @staticmethod + def needs_defining(var: Local) -> bool: + return ( + not var.defined and + not var.is_array() and + var.name != "unused" + ) + + @staticmethod + def is_live(var: Local) -> bool: + return ( + var.defined and + var.name != "unused" + ) + + def first_input_not_cleared(self) -> str: + for input in self.inputs: + if input.defined: + return input.name + return "" + + def clear_inputs(self, reason:str) -> None: + while self.inputs: + tos = self.inputs.pop() + if self.is_live(tos) and not tos.is_array(): + raise StackError( + f"Input '{tos.name}' is still live {reason}" + ) + self.stack.pop(tos.item) + + def clear_dead_inputs(self) -> None: + live = "" + while self.inputs: + tos = self.inputs[-1] + if self.is_live(tos): + live = tos.name + break + self.inputs.pop() + self.stack.pop(tos.item) + for var in self.inputs: + if not var.defined and not var.is_array() and var.name != "unused": + raise StackError( + f"Input '{var.name}' is not live, but '{live}' is" + ) + + def _push_defined_outputs(self) -> None: + defined_output = "" + for output in self.outputs: + if output.defined and not output.in_memory: + defined_output = output.name + if not defined_output: + return + self.clear_inputs(f"when output '{defined_output}' is defined") + undefined = "" + for out in self.outputs: + if out.defined: + if undefined: + f"Locals not defined in stack order. " + f"Expected '{undefined}' to be defined before '{out.name}'" + else: + undefined = out.name + while self.outputs and not self.needs_defining(self.outputs[0]): + out = self.outputs.pop(0) + self.stack.push(out) + + def locals_cached(self) -> bool: + for out in self.outputs: + if out.defined: + return True + return False + + def flush(self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool = True) -> None: + self.clear_dead_inputs() + self._push_defined_outputs() + self.stack.flush(out, cast_type, extract_bits) + + def save(self, out: CWriter) -> None: + assert self.spilled >= 0 + if self.spilled == 0: + self.flush(out) + out.start_line() + out.emit("_PyFrame_SetStackPointer(frame, stack_pointer);\n") + self.spilled += 1 + + def reload(self, out: CWriter) -> None: + if self.spilled == 0: + raise StackError("Cannot reload stack as it hasn't been saved") + assert self.spilled > 0 + self.spilled -= 1 + if self.spilled == 0: + out.start_line() + out.emit("stack_pointer = _PyFrame_GetStackPointer(frame);\n") + + @staticmethod + def for_uop(stack: Stack, uop: Uop, extract_bits: bool = True) -> tuple[list[str], "Storage"]: + code_list: list[str] = [] + inputs: list[Local] = [] + peeks: list[Local] = [] + for input in reversed(uop.stack.inputs): + code, local = stack.pop(input, extract_bits) + code_list.append(code) + if input.peek: + peeks.append(local) + else: + inputs.append(local) + inputs.reverse() + peeks.reverse() + for peek in peeks: + stack.push(peek) + top_offset = stack.top_offset.copy() + for ouput in uop.stack.outputs: + if ouput.is_array() and ouput.used and not ouput.peek: + c_offset = top_offset.to_c() + top_offset.push(ouput) + code_list.append(f"{ouput.name} = &stack_pointer[{c_offset}];\n") + else: + top_offset.push(ouput) + for var in inputs: + stack.push(var) + outputs = [ Local.undefined(var) for var in uop.stack.outputs if not var.peek ] + return code_list, Storage(stack, inputs, outputs, peeks) + + @staticmethod + def copy_list(arg: list[Local]) -> list[Local]: + return [ l.copy() for l in arg ] + + def copy(self) -> "Storage": + new_stack = self.stack.copy() + variables = { var.name: var for var in new_stack.variables } + inputs = [ variables[var.name] for var in self.inputs] + assert [v.name for v in inputs] == [v.name for v in self.inputs], (inputs, self.inputs) + return Storage( + new_stack, inputs, + self.copy_list(self.outputs), self.copy_list(self.peeks) + ) + + def sanity_check(self) -> None: + names: set[str] = set() + for var in self.inputs: + if var.name in names: + raise StackError(f"Duplicate name {var.name}") + names.add(var.name) + names = set() + for var in self.outputs: + if var.name in names: + raise StackError(f"Duplicate name {var.name}") + names.add(var.name) + names = set() + for var in self.stack.variables: + if var.name in names: + raise StackError(f"Duplicate name {var.name}") + names.add(var.name) + + def is_flushed(self) -> bool: + for var in self.outputs: + if var.defined and not var.in_memory: + return False + return self.stack.is_flushed() + + def merge(self, other: "Storage", out: CWriter) -> None: + self.sanity_check() + if len(self.inputs) != len(other.inputs): + self.clear_dead_inputs() + other.clear_dead_inputs() + if len(self.inputs) != len(other.inputs): + diff = self.inputs[-1] if len(self.inputs) > len(other.inputs) else other.inputs[-1] + raise StackError(f"Unmergeable inputs. Differing state of '{diff.name}'") + for var, other_var in zip(self.inputs, other.inputs): + if var.defined != other_var.defined: + raise StackError(f"'{var.name}' is cleared on some paths, but not all") + if len(self.outputs) != len(other.outputs): + self._push_defined_outputs() + other._push_defined_outputs() + if len(self.outputs) != len(other.outputs): + var = self.outputs[0] if len(self.outputs) > len(other.outputs) else other.outputs[0] + raise StackError(f"'{var.name}' is set on some paths, but not all") + self.stack.merge(other.stack, out) + self.sanity_check() + + def push_outputs(self) -> None: + if self.spilled: + raise StackError(f"Unbalanced stack spills") + self.clear_inputs("at the end of the micro-op") + if self.inputs: + raise StackError(f"Input variable '{self.inputs[-1].name}' is still live") + self._push_defined_outputs() + if self.outputs: + for out in self.outputs: + if self.needs_defining(out): + raise StackError(f"Output variable '{self.outputs[0].name}' is not defined") + self.stack.push(out) + self.outputs = [] + + def as_comment(self) -> str: + stack_comment = self.stack.as_comment() + next_line = "\n " + inputs = ", ".join([var.compact_str() for var in self.inputs]) + outputs = ", ".join([var.compact_str() for var in self.outputs]) + peeks = ", ".join([var.name for var in self.peeks]) + return f"{stack_comment[:-2]}{next_line}inputs: {inputs}{next_line}outputs: {outputs}{next_line}peeks: {peeks} */" diff --git a/Tools/cases_generator/tier1_generator.py b/Tools/cases_generator/tier1_generator.py index c749896c2cb7f6..1b116a578c5a86 100644 --- a/Tools/cases_generator/tier1_generator.py +++ b/Tools/cases_generator/tier1_generator.py @@ -22,10 +22,11 @@ write_header, type_and_null, Emitter, + TokenIterator, ) from cwriter import CWriter from typing import TextIO -from stack import Local, Stack, StackError, get_stack_effect +from stack import Local, Stack, StackError, get_stack_effect, Storage DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h" @@ -47,7 +48,7 @@ def declare_variables(inst: Instruction, out: CWriter) -> None: try: stack = get_stack_effect(inst) except StackError as ex: - raise analysis_error(ex.args[0], inst.where) + raise analysis_error(ex.args[0], inst.where) from None required = set(stack.defined) required.discard("unused") for part in inst.parts: @@ -70,46 +71,26 @@ def write_uop( stack: Stack, inst: Instruction, braces: bool, -) -> int: +) -> tuple[int, Stack]: # out.emit(stack.as_comment() + "\n") if isinstance(uop, Skip): entries = "entries" if uop.size > 1 else "entry" emitter.emit(f"/* Skip {uop.size} cache {entries} */\n") - return offset + uop.size + return (offset + uop.size), stack if isinstance(uop, Flush): emitter.emit(f"// flush\n") stack.flush(emitter.out) - return offset + return offset, stack try: locals: dict[str, Local] = {} emitter.out.start_line() if braces: emitter.out.emit(f"// {uop.name}\n") - peeks: list[Local] = [] - for var in reversed(uop.stack.inputs): - code, local = stack.pop(var) - emitter.emit(code) - if var.peek: - peeks.append(local) - if local.defined: - locals[local.name] = local - # Push back the peeks, so that they remain on the logical - # stack, but their values are cached. - while peeks: - stack.push(peeks.pop()) - if braces: emitter.emit("{\n") - emitter.out.emit(stack.define_output_arrays(uop.stack.outputs)) - outputs: list[Local] = [] - for var in uop.stack.outputs: - if not var.peek: - if var.name in locals: - local = locals[var.name] - elif var.name == "unused": - local = Local.unused(var) - else: - local = Local.local(var) - outputs.append(local) + code_list, storage = Storage.for_uop(stack, uop) + emitter._print_storage(storage) + for code in code_list: + emitter.emit(code) for cache in uop.caches: if cache.name != "unused": @@ -125,17 +106,13 @@ def write_uop( if inst.family is None: emitter.emit(f"(void){cache.name};\n") offset += cache.size - emitter.emit_tokens(uop, stack, inst) - for output in outputs: - if output.name in uop.deferred_refs.values(): - # We've already spilled this when emitting tokens - output.cached = False - stack.push(output) + + storage = emitter.emit_tokens(uop, storage, inst) if braces: emitter.out.start_line() emitter.emit("}\n") # emitter.emit(stack.as_comment() + "\n") - return offset + return offset, storage.stack except StackError as ex: raise analysis_error(ex.args[0], uop.body[0]) @@ -197,10 +174,11 @@ def generate_tier1( for part in inst.parts: # Only emit braces if more than one uop insert_braces = len([p for p in inst.parts if isinstance(p, Uop)]) > 1 - offset = write_uop(part, emitter, offset, stack, inst, insert_braces) + offset, stack = write_uop(part, emitter, offset, stack, inst, insert_braces) out.start_line() + + stack.flush(out) if not inst.parts[-1].properties.always_exits: - stack.flush(out) out.emit("DISPATCH();\n") out.start_line() out.emit("}") diff --git a/Tools/cases_generator/tier2_generator.py b/Tools/cases_generator/tier2_generator.py index b7c70fdad085fd..634848c10309d5 100644 --- a/Tools/cases_generator/tier2_generator.py +++ b/Tools/cases_generator/tier2_generator.py @@ -20,11 +20,13 @@ write_header, type_and_null, Emitter, + TokenIterator, + always_true, ) from cwriter import CWriter from typing import TextIO, Iterator from lexer import Token -from stack import Local, Stack, StackError, get_stack_effect +from stack import Local, Stack, StackError, Storage DEFAULT_OUTPUT = ROOT / "Python/executor_cases.c.h" @@ -32,7 +34,7 @@ def declare_variable( var: StackItem, uop: Uop, required: set[str], out: CWriter ) -> None: - if var.name not in required: + if not var.used or var.name not in required: return required.remove(var.name) type, null = type_and_null(var) @@ -52,7 +54,7 @@ def declare_variables(uop: Uop, out: CWriter) -> None: for var in reversed(uop.stack.inputs): stack.pop(var) for var in uop.stack.outputs: - stack.push(Local.unused(var)) + stack.push(Local.undefined(var)) required = set(stack.defined) required.discard("unused") for var in reversed(uop.stack.inputs): @@ -69,88 +71,103 @@ def __init__(self, out: CWriter): def error_if( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: self.out.emit_at("if ", tkn) - self.emit(next(tkn_iter)) + lparen = next(tkn_iter) + self.emit(lparen) + assert lparen.kind == "LPAREN" + first_tkn = next(tkn_iter) + self.out.emit(first_tkn) emit_to(self.out, tkn_iter, "COMMA") label = next(tkn_iter).text next(tkn_iter) # RPAREN next(tkn_iter) # Semi colon self.emit(") JUMP_TO_ERROR();\n") + return not always_true(first_tkn) + def error_no_pop( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - stack: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: next(tkn_iter) # LPAREN next(tkn_iter) # RPAREN next(tkn_iter) # Semi colon self.out.emit_at("JUMP_TO_ERROR();", tkn) + return False def deopt_if( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - unused: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: self.out.emit_at("if ", tkn) - self.emit(next(tkn_iter)) + lparen = next(tkn_iter) + self.emit(lparen) + assert lparen.kind == "LPAREN" + first_tkn = tkn_iter.peek() emit_to(self.out, tkn_iter, "RPAREN") next(tkn_iter) # Semi colon self.emit(") {\n") self.emit("UOP_STAT_INC(uopcode, miss);\n") self.emit("JUMP_TO_JUMP_TARGET();\n") self.emit("}\n") + return not always_true(first_tkn) def exit_if( # type: ignore[override] self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - unused: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: self.out.emit_at("if ", tkn) - self.emit(next(tkn_iter)) + lparen = next(tkn_iter) + self.emit(lparen) + first_tkn = tkn_iter.peek() emit_to(self.out, tkn_iter, "RPAREN") next(tkn_iter) # Semi colon self.emit(") {\n") self.emit("UOP_STAT_INC(uopcode, miss);\n") self.emit("JUMP_TO_JUMP_TARGET();\n") self.emit("}\n") + return not always_true(first_tkn) def oparg( self, tkn: Token, - tkn_iter: Iterator[Token], + tkn_iter: TokenIterator, uop: Uop, - unused: Stack, + storage: Storage, inst: Instruction | None, - ) -> None: + ) -> bool: if not uop.name.endswith("_0") and not uop.name.endswith("_1"): self.emit(tkn) - return + return True amp = next(tkn_iter) if amp.text != "&": self.emit(tkn) self.emit(amp) - return + return True one = next(tkn_iter) assert one.text == "1" self.out.emit_at(uop.name[-1], tkn) + return True -def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> None: +def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> Stack: locals: dict[str, Local] = {} try: emitter.out.start_line() @@ -160,19 +177,9 @@ def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> None: elif uop.properties.const_oparg >= 0: emitter.emit(f"oparg = {uop.properties.const_oparg};\n") emitter.emit(f"assert(oparg == CURRENT_OPARG());\n") - for var in reversed(uop.stack.inputs): - code, local = stack.pop(var) + code_list, storage = Storage.for_uop(stack, uop) + for code in code_list: emitter.emit(code) - if local.defined: - locals[local.name] = local - emitter.emit(stack.define_output_arrays(uop.stack.outputs)) - outputs: list[Local] = [] - for var in uop.stack.outputs: - if var.name in locals: - local = locals[var.name] - else: - local = Local.local(var) - outputs.append(local) for cache in uop.caches: if cache.name != "unused": if cache.size == 4: @@ -181,15 +188,10 @@ def write_uop(uop: Uop, emitter: Emitter, stack: Stack) -> None: type = f"uint{cache.size*16}_t " cast = f"uint{cache.size*16}_t" emitter.emit(f"{type}{cache.name} = ({cast})CURRENT_OPERAND();\n") - emitter.emit_tokens(uop, stack, None) - for output in outputs: - if output.name in uop.deferred_refs.values(): - # We've already spilled this when emitting tokens - output.cached = False - stack.push(output) + storage = emitter.emit_tokens(uop, storage, None) except StackError as ex: raise analysis_error(ex.args[0], uop.body[0]) from None - + return storage.stack SKIPS = ("_EXTENDED_ARG",) @@ -226,7 +228,7 @@ def generate_tier2( out.emit(f"case {uop.name}: {{\n") declare_variables(uop, out) stack = Stack() - write_uop(uop, emitter, stack) + stack = write_uop(uop, emitter, stack) out.start_line() if not uop.properties.always_exits: stack.flush(out) diff --git a/Tools/jit/_stencils.py b/Tools/jit/_stencils.py index 1c6a9edb39840d..bbb52f391f4b01 100644 --- a/Tools/jit/_stencils.py +++ b/Tools/jit/_stencils.py @@ -2,7 +2,6 @@ import dataclasses import enum -import sys import typing import _schema @@ -103,8 +102,8 @@ class HoleValue(enum.Enum): HoleValue.OPERAND_HI: "(instruction->operand >> 32)", HoleValue.OPERAND_LO: "(instruction->operand & UINT32_MAX)", HoleValue.TARGET: "instruction->target", - HoleValue.JUMP_TARGET: "instruction_starts[instruction->jump_target]", - HoleValue.ERROR_TARGET: "instruction_starts[instruction->error_target]", + HoleValue.JUMP_TARGET: "state->instruction_starts[instruction->jump_target]", + HoleValue.ERROR_TARGET: "state->instruction_starts[instruction->error_target]", HoleValue.ZERO: "", } @@ -125,6 +124,7 @@ class Hole: symbol: str | None # ...plus this addend: addend: int + need_state: bool = False func: str = dataclasses.field(init=False) # Convenience method: replace = dataclasses.replace @@ -157,10 +157,12 @@ def as_c(self, where: str) -> str: if value: value += " + " value += f"(uintptr_t)&{self.symbol}" - if _signed(self.addend): + if _signed(self.addend) or not value: if value: value += " + " value += f"{_signed(self.addend):#x}" + if self.need_state: + return f"{self.func}({location}, {value}, state);" return f"{self.func}({location}, {value});" @@ -175,7 +177,6 @@ class Stencil: body: bytearray = dataclasses.field(default_factory=bytearray, init=False) holes: list[Hole] = dataclasses.field(default_factory=list, init=False) disassembly: list[str] = dataclasses.field(default_factory=list, init=False) - trampolines: dict[str, int] = dataclasses.field(default_factory=dict, init=False) def pad(self, alignment: int) -> None: """Pad the stencil to the given alignment.""" @@ -184,39 +185,6 @@ def pad(self, alignment: int) -> None: self.disassembly.append(f"{offset:x}: {' '.join(['00'] * padding)}") self.body.extend([0] * padding) - def emit_aarch64_trampoline(self, hole: Hole, alignment: int) -> Hole: - """Even with the large code model, AArch64 Linux insists on 28-bit jumps.""" - assert hole.symbol is not None - reuse_trampoline = hole.symbol in self.trampolines - if reuse_trampoline: - # Re-use the base address of the previously created trampoline - base = self.trampolines[hole.symbol] - else: - self.pad(alignment) - base = len(self.body) - new_hole = hole.replace(addend=base, symbol=None, value=HoleValue.DATA) - - if reuse_trampoline: - return new_hole - - self.disassembly += [ - f"{base + 4 * 0:x}: 58000048 ldr x8, 8", - f"{base + 4 * 1:x}: d61f0100 br x8", - f"{base + 4 * 2:x}: 00000000", - f"{base + 4 * 2:016x}: R_AARCH64_ABS64 {hole.symbol}", - f"{base + 4 * 3:x}: 00000000", - ] - for code in [ - 0x58000048.to_bytes(4, sys.byteorder), - 0xD61F0100.to_bytes(4, sys.byteorder), - 0x00000000.to_bytes(4, sys.byteorder), - 0x00000000.to_bytes(4, sys.byteorder), - ]: - self.body.extend(code) - self.holes.append(hole.replace(offset=base + 8, kind="R_AARCH64_ABS64")) - self.trampolines[hole.symbol] = base - return new_hole - def remove_jump(self, *, alignment: int = 1) -> None: """Remove a zero-length continuation jump, if it exists.""" hole = max(self.holes, key=lambda hole: hole.offset) @@ -282,8 +250,14 @@ class StencilGroup: default_factory=dict, init=False ) _got: dict[str, int] = dataclasses.field(default_factory=dict, init=False) - - def process_relocations(self, *, alignment: int = 1) -> None: + _trampolines: set[int] = dataclasses.field(default_factory=set, init=False) + + def process_relocations( + self, + known_symbols: dict[str, int], + *, + alignment: int = 1, + ) -> None: """Fix up all GOT and internal relocations for this stencil group.""" for hole in self.code.holes.copy(): if ( @@ -291,9 +265,17 @@ def process_relocations(self, *, alignment: int = 1) -> None: in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26", "ARM64_RELOC_BRANCH26"} and hole.value is HoleValue.ZERO ): - new_hole = self.data.emit_aarch64_trampoline(hole, alignment) - self.code.holes.remove(hole) - self.code.holes.append(new_hole) + hole.func = "patch_aarch64_trampoline" + hole.need_state = True + assert hole.symbol is not None + if hole.symbol in known_symbols: + ordinal = known_symbols[hole.symbol] + else: + ordinal = len(known_symbols) + known_symbols[hole.symbol] = ordinal + self._trampolines.add(ordinal) + hole.addend = ordinal + hole.symbol = None self.code.remove_jump(alignment=alignment) self.code.pad(alignment) self.data.pad(8) @@ -348,9 +330,20 @@ def _emit_global_offset_table(self) -> None: ) self.data.body.extend([0] * 8) + def _get_trampoline_mask(self) -> str: + bitmask: int = 0 + trampoline_mask: list[str] = [] + for ordinal in self._trampolines: + bitmask |= 1 << ordinal + while bitmask: + word = bitmask & ((1 << 32) - 1) + trampoline_mask.append(f"{word:#04x}") + bitmask >>= 32 + return "{" + ", ".join(trampoline_mask) + "}" + def as_c(self, opname: str) -> str: """Dump this hole as a StencilGroup initializer.""" - return f"{{emit_{opname}, {len(self.code.body)}, {len(self.data.body)}}}" + return f"{{emit_{opname}, {len(self.code.body)}, {len(self.data.body)}, {self._get_trampoline_mask()}}}" def symbol_to_value(symbol: str) -> tuple[HoleValue, str | None]: diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index 6c7b48f1f37865..5eb316e782fda8 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -44,6 +44,7 @@ class _Target(typing.Generic[_S, _R]): stable: bool = False debug: bool = False verbose: bool = False + known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) def _compute_digest(self, out: pathlib.Path) -> str: hasher = hashlib.sha256() @@ -95,7 +96,9 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: if group.data.body: line = f"0: {str(bytes(group.data.body)).removeprefix('b')}" group.data.disassembly.append(line) - group.process_relocations(alignment=self.alignment) + group.process_relocations( + known_symbols=self.known_symbols, alignment=self.alignment + ) return group def _handle_section(self, section: _S, group: _stencils.StencilGroup) -> None: @@ -139,9 +142,6 @@ async def _compile( "-fno-plt", # Don't call stack-smashing canaries that we can't find or patch: "-fno-stack-protector", - # On aarch64 Linux, intrinsics were being emitted and this flag - # was required to disable them. - "-mno-outline-atomics", "-std=c11", *self.args, ] @@ -234,7 +234,7 @@ def build( if comment: file.write(f"// {comment}\n") file.write("\n") - for line in _writer.dump(stencil_groups): + for line in _writer.dump(stencil_groups, self.known_symbols): file.write(f"{line}\n") try: jit_stencils_new.replace(jit_stencils) @@ -527,7 +527,12 @@ def get_target(host: str) -> _COFF | _ELF | _MachO: args = ["-fms-runtime-lib=dll"] target = _COFF(host, alignment=8, args=args) elif re.fullmatch(r"aarch64-.*-linux-gnu", host): - args = ["-fpic"] + args = [ + "-fpic", + # On aarch64 Linux, intrinsics were being emitted and this flag + # was required to disable them. + "-mno-outline-atomics", + ] target = _ELF(host, alignment=8, args=args) elif re.fullmatch(r"i686-pc-windows-msvc", host): args = ["-DPy_NO_ENABLE_SHARED"] diff --git a/Tools/jit/_writer.py b/Tools/jit/_writer.py index 9d11094f85c7ff..7b99d10310a645 100644 --- a/Tools/jit/_writer.py +++ b/Tools/jit/_writer.py @@ -2,17 +2,24 @@ import itertools import typing +import math import _stencils -def _dump_footer(groups: dict[str, _stencils.StencilGroup]) -> typing.Iterator[str]: +def _dump_footer( + groups: dict[str, _stencils.StencilGroup], symbols: dict[str, int] +) -> typing.Iterator[str]: + symbol_mask_size = max(math.ceil(len(symbols) / 32), 1) + yield f'static_assert(SYMBOL_MASK_WORDS >= {symbol_mask_size}, "SYMBOL_MASK_WORDS too small");' + yield "" yield "typedef struct {" yield " void (*emit)(" yield " unsigned char *code, unsigned char *data, _PyExecutorObject *executor," - yield " const _PyUOpInstruction *instruction, uintptr_t instruction_starts[]);" + yield " const _PyUOpInstruction *instruction, jit_state *state);" yield " size_t code_size;" yield " size_t data_size;" + yield " symbol_mask trampoline_mask;" yield "} StencilGroup;" yield "" yield f"static const StencilGroup trampoline = {groups['trampoline'].as_c('trampoline')};" @@ -23,13 +30,18 @@ def _dump_footer(groups: dict[str, _stencils.StencilGroup]) -> typing.Iterator[s continue yield f" [{opname}] = {group.as_c(opname)}," yield "};" + yield "" + yield f"static const void * const symbols_map[{max(len(symbols), 1)}] = {{" + for symbol, ordinal in symbols.items(): + yield f" [{ordinal}] = &{symbol}," + yield "};" def _dump_stencil(opname: str, group: _stencils.StencilGroup) -> typing.Iterator[str]: yield "void" yield f"emit_{opname}(" yield " unsigned char *code, unsigned char *data, _PyExecutorObject *executor," - yield " const _PyUOpInstruction *instruction, uintptr_t instruction_starts[])" + yield " const _PyUOpInstruction *instruction, jit_state *state)" yield "{" for part, stencil in [("code", group.code), ("data", group.data)]: for line in stencil.disassembly: @@ -58,8 +70,10 @@ def _dump_stencil(opname: str, group: _stencils.StencilGroup) -> typing.Iterator yield "" -def dump(groups: dict[str, _stencils.StencilGroup]) -> typing.Iterator[str]: +def dump( + groups: dict[str, _stencils.StencilGroup], symbols: dict[str, int] +) -> typing.Iterator[str]: """Yield a JIT compiler line-by-line as a C header file.""" for opname, group in sorted(groups.items()): yield from _dump_stencil(opname, group) - yield from _dump_footer(groups) + yield from _dump_footer(groups, symbols) diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp index 6f50200dc7b251..1e0df5084ff079 100644 --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -3100,7 +3100,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { } else { BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows Server 2003 or earlier"); } - BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows Server 2012 or later is required to continue installation"); + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows Server 2016 or later is required to continue installation"); } else { if (IsWindows10OrGreater()) { BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Target OS is Windows 10 or later"); @@ -3116,7 +3116,7 @@ class PythonBootstrapperApplication : public CBalBaseBootstrapperApplication { } else { BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Detected Windows XP or earlier"); } - BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows 8.1 or later is required to continue installation"); + BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "Windows 10 or later is required to continue installation"); } LocGetString(_wixLoc, L"#(loc.FailureOldOS)", &pLocString); diff --git a/Tools/msi/purge.py b/Tools/msi/purge.py index e25219a6caf9d4..4a13d368d7c744 100644 --- a/Tools/msi/purge.py +++ b/Tools/msi/purge.py @@ -51,14 +51,6 @@ "test_pdb.msi", "tools.msi", "ucrt.msi", - "Windows6.0-KB2999226-x64.msu", - "Windows6.0-KB2999226-x86.msu", - "Windows6.1-KB2999226-x64.msu", - "Windows6.1-KB2999226-x86.msu", - "Windows8.1-KB2999226-x64.msu", - "Windows8.1-KB2999226-x86.msu", - "Windows8-RT-KB2999226-x64.msu", - "Windows8-RT-KB2999226-x86.msu", ] PATHS = [ "python-{}.exe".format(m.group(0)), diff --git a/Tools/peg_generator/pegen/c_generator.py b/Tools/peg_generator/pegen/c_generator.py index 547c55dce130f7..a4951d05e80ebd 100644 --- a/Tools/peg_generator/pegen/c_generator.py +++ b/Tools/peg_generator/pegen/c_generator.py @@ -3,7 +3,7 @@ import re from dataclasses import dataclass, field from enum import Enum -from typing import IO, Any, Dict, List, Optional, Set, Text, Tuple +from typing import IO, Any, Callable, Dict, List, Optional, Set, Text, Tuple from pegen import grammar from pegen.grammar import ( @@ -130,7 +130,7 @@ def __init__( self.gen = parser_generator self.exact_tokens = exact_tokens self.non_exact_tokens = non_exact_tokens - self.cache: Dict[Any, FunctionCall] = {} + self.cache: Dict[str, str] = {} self.cleanup_statements: List[str] = [] def keyword_helper(self, keyword: str) -> FunctionCall: @@ -206,21 +206,6 @@ def visit_StringLeaf(self, node: StringLeaf) -> FunctionCall: comment=f"token='{val}'", ) - def visit_Rhs(self, node: Rhs) -> FunctionCall: - if node in self.cache: - return self.cache[node] - if node.can_be_inlined: - self.cache[node] = self.generate_call(node.alts[0].items[0]) - else: - name = self.gen.artificial_rule_from_rhs(node) - self.cache[node] = FunctionCall( - assigned_variable=f"{name}_var", - function=f"{name}_rule", - arguments=["p"], - comment=f"{node}", - ) - return self.cache[node] - def visit_NamedItem(self, node: NamedItem) -> FunctionCall: call = self.generate_call(node.item) if node.name: @@ -302,44 +287,62 @@ def visit_Opt(self, node: Opt) -> FunctionCall: comment=f"{node}", ) - def visit_Repeat0(self, node: Repeat0) -> FunctionCall: - if node in self.cache: - return self.cache[node] - name = self.gen.artificial_rule_from_repeat(node.node, False) - self.cache[node] = FunctionCall( + def _generate_artificial_rule_call( + self, + node: Any, + prefix: str, + rule_generation_func: Callable[[], str], + return_type: Optional[str] = None, + ) -> FunctionCall: + node_str = f"{node}" + key = f"{prefix}_{node_str}" + if key in self.cache: + name = self.cache[key] + else: + name = rule_generation_func() + self.cache[key] = name + + return FunctionCall( assigned_variable=f"{name}_var", function=f"{name}_rule", arguments=["p"], - return_type="asdl_seq *", - comment=f"{node}", + return_type=return_type, + comment=node_str, + ) + + def visit_Rhs(self, node: Rhs) -> FunctionCall: + if node.can_be_inlined: + return self.generate_call(node.alts[0].items[0]) + + return self._generate_artificial_rule_call( + node, + "rhs", + lambda: self.gen.artificial_rule_from_rhs(node), + ) + + def visit_Repeat0(self, node: Repeat0) -> FunctionCall: + return self._generate_artificial_rule_call( + node, + "repeat0", + lambda: self.gen.artificial_rule_from_repeat(node.node, is_repeat1=False), + "asdl_seq *", ) - return self.cache[node] def visit_Repeat1(self, node: Repeat1) -> FunctionCall: - if node in self.cache: - return self.cache[node] - name = self.gen.artificial_rule_from_repeat(node.node, True) - self.cache[node] = FunctionCall( - assigned_variable=f"{name}_var", - function=f"{name}_rule", - arguments=["p"], - return_type="asdl_seq *", - comment=f"{node}", + return self._generate_artificial_rule_call( + node, + "repeat1", + lambda: self.gen.artificial_rule_from_repeat(node.node, is_repeat1=True), + "asdl_seq *", ) - return self.cache[node] def visit_Gather(self, node: Gather) -> FunctionCall: - if node in self.cache: - return self.cache[node] - name = self.gen.artificial_rule_from_gather(node) - self.cache[node] = FunctionCall( - assigned_variable=f"{name}_var", - function=f"{name}_rule", - arguments=["p"], - return_type="asdl_seq *", - comment=f"{node}", + return self._generate_artificial_rule_call( + node, + "gather", + lambda: self.gen.artificial_rule_from_gather(node), + "asdl_seq *", ) - return self.cache[node] def visit_Group(self, node: Group) -> FunctionCall: return self.generate_call(node.rhs) diff --git a/Tools/peg_generator/pegen/parser_generator.py b/Tools/peg_generator/pegen/parser_generator.py index 8cca7b6c39a5cc..b42b12c8aa0dee 100644 --- a/Tools/peg_generator/pegen/parser_generator.py +++ b/Tools/peg_generator/pegen/parser_generator.py @@ -184,8 +184,6 @@ def artificial_rule_from_repeat(self, node: Plain, is_repeat1: bool) -> str: return name def artificial_rule_from_gather(self, node: Gather) -> str: - self.counter += 1 - name = f"_gather_{self.counter}" self.counter += 1 extra_function_name = f"_loop0_{self.counter}" extra_function_alt = Alt( @@ -197,6 +195,8 @@ def artificial_rule_from_gather(self, node: Gather) -> str: None, Rhs([extra_function_alt]), ) + self.counter += 1 + name = f"_gather_{self.counter}" alt = Alt( [NamedItem("elem", node.node), NamedItem("seq", NameLeaf(extra_function_name))], )