| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This file compiles an abstract syntax tree (AST) into Python bytecode. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-03-24 00:51:50 +01:00
										 |  |  |  * The primary entry point is _PyAST_Compile(), which returns a | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  |  * PyCodeObject.  The compiler makes several passes to build the code | 
					
						
							|  |  |  |  * object: | 
					
						
							|  |  |  |  *   1. Checks for future statements.  See future.c | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  |  *   2. Builds a symbol table.  See symtable.c. | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |  *   3. Generate an instruction sequence. See compiler_mod() in this file, which | 
					
						
							|  |  |  |  *      calls functions from codegen.c. | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |  *   4. Generate a control flow graph and run optimizations on it.  See flowgraph.c. | 
					
						
							|  |  |  |  *   5. Assemble the basic blocks into final code.  See optimize_and_assemble() in | 
					
						
							|  |  |  |  *      this file, and assembler.c. | 
					
						
							| 
									
										
										
										
											2005-10-20 19:59:25 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-02-26 14:51:55 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | #include <stdbool.h>
 | 
					
						
							| 
									
										
										
										
											2021-02-26 14:51:55 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | #include "pycore_ast.h"           // PyAST_Check, _PyAST_GetDocString()
 | 
					
						
							|  |  |  | #include "pycore_compile.h"
 | 
					
						
							|  |  |  | #include "pycore_flowgraph.h"
 | 
					
						
							|  |  |  | #include "pycore_pystate.h"       // _Py_GetConfig()
 | 
					
						
							|  |  |  | #include "pycore_setobject.h"     // _PySet_NextEntry()
 | 
					
						
							| 
									
										
										
										
											2021-05-02 13:02:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | #include "cpython/code.h"
 | 
					
						
							| 
									
										
										
										
											2021-02-26 14:51:55 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | #undef SUCCESS
 | 
					
						
							|  |  |  | #undef ERROR
 | 
					
						
							|  |  |  | #define SUCCESS 0
 | 
					
						
							|  |  |  | #define ERROR -1
 | 
					
						
							| 
									
										
										
										
											2022-09-01 21:36:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | #define RETURN_IF_ERROR(X)  \
 | 
					
						
							| 
									
										
										
										
											2024-11-08 00:03:11 +01:00
										 |  |  |     do {                    \ | 
					
						
							|  |  |  |         if ((X) == -1) {    \ | 
					
						
							|  |  |  |             return ERROR;   \ | 
					
						
							|  |  |  |         }                   \ | 
					
						
							|  |  |  |     } while (0) | 
					
						
							| 
									
										
										
										
											2022-09-01 21:36:47 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | typedef _Py_SourceLocation location; | 
					
						
							|  |  |  | typedef _PyJumpTargetLabel jump_target_label; | 
					
						
							|  |  |  | typedef _PyInstructionSequence instr_sequence; | 
					
						
							|  |  |  | typedef struct _PyCfgBuilder cfg_builder; | 
					
						
							|  |  |  | typedef _PyCompile_FBlockInfo fblockinfo; | 
					
						
							|  |  |  | typedef enum _PyCompile_FBlockType fblocktype; | 
					
						
							| 
									
										
										
										
											2024-08-22 15:08:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-02 18:23:39 +01:00
										 |  |  | /* The following items change on entry and exit of code blocks.
 | 
					
						
							|  |  |  |    They must be saved and restored when returning to a block. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | struct compiler_unit { | 
					
						
							|  |  |  |     PySTEntryObject *u_ste; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int u_scope_type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *u_private;            /* for private name mangling */ | 
					
						
							|  |  |  |     PyObject *u_static_attributes;  /* for class: attributes accessed via self.X */ | 
					
						
							|  |  |  |     PyObject *u_deferred_annotations; /* AnnAssign nodes deferred to the end of compilation */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     instr_sequence *u_instr_sequence; /* codegen output */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int u_nfblocks; | 
					
						
							|  |  |  |     int u_in_inlined_comp; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     _PyCompile_FBlockInfo u_fblock[CO_MAXBLOCKS]; | 
					
						
							| 
									
										
										
										
											2024-09-02 18:23:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     _PyCompile_CodeUnitMetadata u_metadata; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This struct captures the global state of a compilation.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The u pointer points to the current compilation unit, while units | 
					
						
							|  |  |  | for enclosing blocks are stored in c_stack.     The u and c_stack are | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | managed by _PyCompile_EnterScope() and _PyCompile_ExitScope(). | 
					
						
							| 
									
										
										
										
											2024-09-02 18:23:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Note that we don't track recursion levels during compilation - the | 
					
						
							|  |  |  | task of detecting and rejecting excessive levels of nesting is | 
					
						
							|  |  |  | handled by the symbol analysis pass. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | typedef struct _PyCompiler { | 
					
						
							| 
									
										
										
										
											2024-09-02 18:23:39 +01:00
										 |  |  |     PyObject *c_filename; | 
					
						
							|  |  |  |     struct symtable *c_st; | 
					
						
							|  |  |  |     _PyFutureFeatures c_future;  /* module's __future__ */ | 
					
						
							|  |  |  |     PyCompilerFlags c_flags; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int c_optimize;              /* optimization level */ | 
					
						
							|  |  |  |     int c_interactive;           /* true if in interactive mode */ | 
					
						
							|  |  |  |     PyObject *c_const_cache;     /* Python dict holding all constants,
 | 
					
						
							|  |  |  |                                     including names tuple */ | 
					
						
							|  |  |  |     struct compiler_unit *u;     /* compiler state for current block */ | 
					
						
							|  |  |  |     PyObject *c_stack;           /* Python list holding compiler_unit ptrs */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool c_save_nested_seqs;     /* if true, construct recursive instruction sequences
 | 
					
						
							|  |  |  |                                   * (including instructions for nested code objects) | 
					
						
							|  |  |  |                                   */ | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | } compiler; | 
					
						
							| 
									
										
										
										
											2024-09-02 18:23:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | compiler_setup(compiler *c, mod_ty mod, PyObject *filename, | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |                PyCompilerFlags *flags, int optimize, PyArena *arena) | 
					
						
							| 
									
										
										
										
											2024-07-08 21:02:01 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     PyCompilerFlags local_flags = _PyCompilerFlags_INIT; | 
					
						
							| 
									
										
										
										
											2024-07-08 21:02:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     c->c_const_cache = PyDict_New(); | 
					
						
							|  |  |  |     if (!c->c_const_cache) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-07-10 17:09:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     c->c_stack = PyList_New(0); | 
					
						
							|  |  |  |     if (!c->c_stack) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-07-10 17:09:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     c->c_filename = Py_NewRef(filename); | 
					
						
							|  |  |  |     if (!_PyFuture_FromAST(mod, filename, &c->c_future)) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!flags) { | 
					
						
							|  |  |  |         flags = &local_flags; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int merged = c->c_future.ff_features | flags->cf_flags; | 
					
						
							|  |  |  |     c->c_future.ff_features = merged; | 
					
						
							|  |  |  |     flags->cf_flags = merged; | 
					
						
							|  |  |  |     c->c_flags = *flags; | 
					
						
							|  |  |  |     c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize; | 
					
						
							|  |  |  |     c->c_save_nested_seqs = false; | 
					
						
							| 
									
										
										
										
											2024-07-10 17:09:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     if (!_PyAST_Optimize(mod, arena, c->c_optimize, merged)) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     c->c_st = _PySymtable_Build(mod, filename, &c->c_future); | 
					
						
							|  |  |  |     if (c->c_st == NULL) { | 
					
						
							|  |  |  |         if (!PyErr_Occurred()) { | 
					
						
							|  |  |  |             PyErr_SetString(PyExc_SystemError, "no symtable"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							| 
									
										
										
										
											2024-07-10 17:09:45 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | compiler_free(compiler *c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (c->c_st) { | 
					
						
							|  |  |  |         _PySymtable_Free(c->c_st); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_XDECREF(c->c_filename); | 
					
						
							|  |  |  |     Py_XDECREF(c->c_const_cache); | 
					
						
							|  |  |  |     Py_XDECREF(c->c_stack); | 
					
						
							|  |  |  |     PyMem_Free(c); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static compiler* | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags, | 
					
						
							|  |  |  |              int optimize, PyArena *arena) | 
					
						
							| 
									
										
										
										
											2024-08-22 15:08:16 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     compiler *c = PyMem_Calloc(1, sizeof(compiler)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     if (c == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (compiler_setup(c, mod, filename, pflags, optimize, arena) < 0) { | 
					
						
							|  |  |  |         compiler_free(c); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return c; | 
					
						
							| 
									
										
										
										
											2024-08-22 15:08:16 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | compiler_unit_free(struct compiler_unit *u) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_CLEAR(u->u_instr_sequence); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_ste); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_name); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_qualname); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_consts); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_names); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_varnames); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_freevars); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_cellvars); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_metadata.u_fasthidden); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_private); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_static_attributes); | 
					
						
							|  |  |  |     Py_CLEAR(u->u_deferred_annotations); | 
					
						
							|  |  |  |     PyMem_Free(u); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define CAPSULE_NAME "compile.c compiler unit"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_MaybeAddStaticAttributeToClass(compiler *c, expr_ty e) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(e->kind == Attribute_kind); | 
					
						
							|  |  |  |     expr_ty attr_value = e->v.Attribute.value; | 
					
						
							|  |  |  |     if (attr_value->kind != Name_kind || | 
					
						
							|  |  |  |         e->v.Attribute.ctx != Store || | 
					
						
							|  |  |  |         !_PyUnicode_EqualToASCIIString(attr_value->v.Name.id, "self")) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return SUCCESS; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_ssize_t stack_size = PyList_GET_SIZE(c->c_stack); | 
					
						
							|  |  |  |     for (Py_ssize_t i = stack_size - 1; i >= 0; i--) { | 
					
						
							|  |  |  |         PyObject *capsule = PyList_GET_ITEM(c->c_stack, i); | 
					
						
							|  |  |  |         struct compiler_unit *u = (struct compiler_unit *)PyCapsule_GetPointer( | 
					
						
							|  |  |  |                                                               capsule, CAPSULE_NAME); | 
					
						
							|  |  |  |         assert(u); | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (u->u_scope_type == COMPILE_SCOPE_CLASS) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             assert(u->u_static_attributes); | 
					
						
							|  |  |  |             RETURN_IF_ERROR(PySet_Add(u->u_static_attributes, e->v.Attribute.attr)); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | compiler_set_qualname(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t stack_size; | 
					
						
							|  |  |  |     struct compiler_unit *u = c->u; | 
					
						
							|  |  |  |     PyObject *name, *base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     base = NULL; | 
					
						
							|  |  |  |     stack_size = PyList_GET_SIZE(c->c_stack); | 
					
						
							|  |  |  |     assert(stack_size >= 1); | 
					
						
							|  |  |  |     if (stack_size > 1) { | 
					
						
							|  |  |  |         int scope, force_global = 0; | 
					
						
							|  |  |  |         struct compiler_unit *parent; | 
					
						
							|  |  |  |         PyObject *mangled, *capsule; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); | 
					
						
							|  |  |  |         parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); | 
					
						
							|  |  |  |         assert(parent); | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (parent->u_scope_type == COMPILE_SCOPE_ANNOTATIONS) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             /* The parent is an annotation scope, so we need to
 | 
					
						
							|  |  |  |                look at the grandparent. */ | 
					
						
							|  |  |  |             if (stack_size == 2) { | 
					
						
							|  |  |  |                 // If we're immediately within the module, we can skip
 | 
					
						
							|  |  |  |                 // the rest and just set the qualname to be the same as name.
 | 
					
						
							|  |  |  |                 u->u_metadata.u_qualname = Py_NewRef(u->u_metadata.u_name); | 
					
						
							|  |  |  |                 return SUCCESS; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             capsule = PyList_GET_ITEM(c->c_stack, stack_size - 2); | 
					
						
							|  |  |  |             parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); | 
					
						
							|  |  |  |             assert(parent); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (u->u_scope_type == COMPILE_SCOPE_FUNCTION | 
					
						
							|  |  |  |             || u->u_scope_type == COMPILE_SCOPE_ASYNC_FUNCTION | 
					
						
							|  |  |  |             || u->u_scope_type == COMPILE_SCOPE_CLASS) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             assert(u->u_metadata.u_name); | 
					
						
							|  |  |  |             mangled = _Py_Mangle(parent->u_private, u->u_metadata.u_name); | 
					
						
							|  |  |  |             if (!mangled) { | 
					
						
							|  |  |  |                 return ERROR; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             scope = _PyST_GetScope(parent->u_ste, mangled); | 
					
						
							|  |  |  |             Py_DECREF(mangled); | 
					
						
							|  |  |  |             RETURN_IF_ERROR(scope); | 
					
						
							|  |  |  |             assert(scope != GLOBAL_IMPLICIT); | 
					
						
							|  |  |  |             if (scope == GLOBAL_EXPLICIT) | 
					
						
							|  |  |  |                 force_global = 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (!force_global) { | 
					
						
							|  |  |  |             if (parent->u_scope_type == COMPILE_SCOPE_FUNCTION | 
					
						
							|  |  |  |                 || parent->u_scope_type == COMPILE_SCOPE_ASYNC_FUNCTION | 
					
						
							|  |  |  |                 || parent->u_scope_type == COMPILE_SCOPE_LAMBDA) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 _Py_DECLARE_STR(dot_locals, ".<locals>"); | 
					
						
							|  |  |  |                 base = PyUnicode_Concat(parent->u_metadata.u_qualname, | 
					
						
							|  |  |  |                                         &_Py_STR(dot_locals)); | 
					
						
							|  |  |  |                 if (base == NULL) { | 
					
						
							|  |  |  |                     return ERROR; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 base = Py_NewRef(parent->u_metadata.u_qualname); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (base != NULL) { | 
					
						
							|  |  |  |         name = PyUnicode_Concat(base, _Py_LATIN1_CHR('.')); | 
					
						
							|  |  |  |         Py_DECREF(base); | 
					
						
							|  |  |  |         if (name == NULL) { | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyUnicode_Append(&name, u->u_metadata.u_name); | 
					
						
							|  |  |  |         if (name == NULL) { | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         name = Py_NewRef(u->u_metadata.u_name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     u->u_metadata.u_qualname = name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Merge const *o* and return constant key object.
 | 
					
						
							|  |  |  |  * If recursive, insert all elements if o is a tuple or frozen set. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static PyObject* | 
					
						
							|  |  |  | const_cache_insert(PyObject *const_cache, PyObject *o, bool recursive) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(PyDict_CheckExact(const_cache)); | 
					
						
							|  |  |  |     // None and Ellipsis are immortal objects, and key is the singleton.
 | 
					
						
							|  |  |  |     // No need to merge object and key.
 | 
					
						
							|  |  |  |     if (o == Py_None || o == Py_Ellipsis) { | 
					
						
							|  |  |  |         return o; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *key = _PyCode_ConstantKey(o); | 
					
						
							|  |  |  |     if (key == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *t; | 
					
						
							|  |  |  |     int res = PyDict_SetDefaultRef(const_cache, key, key, &t); | 
					
						
							|  |  |  |     if (res != 0) { | 
					
						
							|  |  |  |         // o was not inserted into const_cache. t is either the existing value
 | 
					
						
							|  |  |  |         // or NULL (on error).
 | 
					
						
							|  |  |  |         Py_DECREF(key); | 
					
						
							|  |  |  |         return t; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!recursive) { | 
					
						
							|  |  |  |         return key; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // We registered o in const_cache.
 | 
					
						
							|  |  |  |     // When o is a tuple or frozenset, we want to merge its
 | 
					
						
							|  |  |  |     // items too.
 | 
					
						
							|  |  |  |     if (PyTuple_CheckExact(o)) { | 
					
						
							|  |  |  |         Py_ssize_t len = PyTuple_GET_SIZE(o); | 
					
						
							|  |  |  |         for (Py_ssize_t i = 0; i < len; i++) { | 
					
						
							|  |  |  |             PyObject *item = PyTuple_GET_ITEM(o, i); | 
					
						
							|  |  |  |             PyObject *u = const_cache_insert(const_cache, item, recursive); | 
					
						
							|  |  |  |             if (u == NULL) { | 
					
						
							|  |  |  |                 Py_DECREF(key); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // See _PyCode_ConstantKey()
 | 
					
						
							|  |  |  |             PyObject *v;  // borrowed
 | 
					
						
							|  |  |  |             if (PyTuple_CheckExact(u)) { | 
					
						
							|  |  |  |                 v = PyTuple_GET_ITEM(u, 1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 v = u; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (v != item) { | 
					
						
							|  |  |  |                 PyTuple_SET_ITEM(o, i, Py_NewRef(v)); | 
					
						
							|  |  |  |                 Py_DECREF(item); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Py_DECREF(u); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyFrozenSet_CheckExact(o)) { | 
					
						
							|  |  |  |         // *key* is tuple. And its first item is frozenset of
 | 
					
						
							|  |  |  |         // constant keys.
 | 
					
						
							|  |  |  |         // See _PyCode_ConstantKey() for detail.
 | 
					
						
							|  |  |  |         assert(PyTuple_CheckExact(key)); | 
					
						
							|  |  |  |         assert(PyTuple_GET_SIZE(key) == 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_ssize_t len = PySet_GET_SIZE(o); | 
					
						
							|  |  |  |         if (len == 0) {  // empty frozenset should not be re-created.
 | 
					
						
							|  |  |  |             return key; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyObject *tuple = PyTuple_New(len); | 
					
						
							|  |  |  |         if (tuple == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(key); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_ssize_t i = 0, pos = 0; | 
					
						
							|  |  |  |         PyObject *item; | 
					
						
							|  |  |  |         Py_hash_t hash; | 
					
						
							|  |  |  |         while (_PySet_NextEntry(o, &pos, &item, &hash)) { | 
					
						
							|  |  |  |             PyObject *k = const_cache_insert(const_cache, item, recursive); | 
					
						
							|  |  |  |             if (k == NULL) { | 
					
						
							|  |  |  |                 Py_DECREF(tuple); | 
					
						
							|  |  |  |                 Py_DECREF(key); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             PyObject *u; | 
					
						
							|  |  |  |             if (PyTuple_CheckExact(k)) { | 
					
						
							|  |  |  |                 u = Py_NewRef(PyTuple_GET_ITEM(k, 1)); | 
					
						
							|  |  |  |                 Py_DECREF(k); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |                 u = k; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |             PyTuple_SET_ITEM(tuple, i, u);  // Steals reference of u.
 | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Instead of rewriting o, we create new frozenset and embed in the
 | 
					
						
							|  |  |  |         // key tuple.  Caller should get merged frozenset from the key tuple.
 | 
					
						
							|  |  |  |         PyObject *new = PyFrozenSet_New(tuple); | 
					
						
							|  |  |  |         Py_DECREF(tuple); | 
					
						
							|  |  |  |         if (new == NULL) { | 
					
						
							|  |  |  |             Py_DECREF(key); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         assert(PyTuple_GET_ITEM(key, 1) == o); | 
					
						
							|  |  |  |         Py_DECREF(o); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(key, 1, new); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     return key; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject* | 
					
						
							|  |  |  | merge_consts_recursive(PyObject *const_cache, PyObject *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return const_cache_insert(const_cache, o, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Py_ssize_t | 
					
						
							|  |  |  | _PyCompile_DictAddObj(PyObject *dict, PyObject *o) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *v; | 
					
						
							|  |  |  |     Py_ssize_t arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyDict_GetItemRef(dict, o, &v) < 0) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!v) { | 
					
						
							|  |  |  |         arg = PyDict_GET_SIZE(dict); | 
					
						
							|  |  |  |         v = PyLong_FromSsize_t(arg); | 
					
						
							|  |  |  |         if (!v) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (PyDict_SetItem(dict, o, v) < 0) { | 
					
						
							|  |  |  |             Py_DECREF(v); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     else | 
					
						
							|  |  |  |         arg = PyLong_AsLong(v); | 
					
						
							|  |  |  |     Py_DECREF(v); | 
					
						
							|  |  |  |     return arg; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | Py_ssize_t | 
					
						
							|  |  |  | _PyCompile_AddConst(compiler *c, PyObject *o) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *key = merge_consts_recursive(c->c_const_cache, o); | 
					
						
							|  |  |  |     if (key == NULL) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     Py_ssize_t arg = _PyCompile_DictAddObj(c->u->u_metadata.u_consts, key); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     Py_DECREF(key); | 
					
						
							|  |  |  |     return arg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | list2dict(PyObject *list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i, n; | 
					
						
							|  |  |  |     PyObject *v, *k; | 
					
						
							|  |  |  |     PyObject *dict = PyDict_New(); | 
					
						
							|  |  |  |     if (!dict) return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     n = PyList_Size(list); | 
					
						
							|  |  |  |     for (i = 0; i < n; i++) { | 
					
						
							|  |  |  |         v = PyLong_FromSsize_t(i); | 
					
						
							|  |  |  |         if (!v) { | 
					
						
							|  |  |  |             Py_DECREF(dict); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         k = PyList_GET_ITEM(list, i); | 
					
						
							|  |  |  |         if (PyDict_SetItem(dict, k, v) < 0) { | 
					
						
							|  |  |  |             Py_DECREF(v); | 
					
						
							|  |  |  |             Py_DECREF(dict); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(v); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return dict; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Return new dict containing names from src that match scope(s).
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | src is a symbol table dictionary.  If the scope of a name matches | 
					
						
							|  |  |  | either scope_type or flag is set, insert it into the new dict.  The | 
					
						
							|  |  |  | values are integers, starting at offset and increasing by one for | 
					
						
							|  |  |  | each key. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t i = offset, num_keys, key_i; | 
					
						
							|  |  |  |     PyObject *k, *v, *dest = PyDict_New(); | 
					
						
							|  |  |  |     PyObject *sorted_keys; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(offset >= 0); | 
					
						
							|  |  |  |     if (dest == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Sort the keys so that we have a deterministic order on the indexes
 | 
					
						
							|  |  |  |        saved in the returned dictionary.  These indexes are used as indexes | 
					
						
							|  |  |  |        into the free and cell var storage.  Therefore if they aren't | 
					
						
							|  |  |  |        deterministic, then the generated bytecode is not deterministic. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     sorted_keys = PyDict_Keys(src); | 
					
						
							|  |  |  |     if (sorted_keys == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(dest); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyList_Sort(sorted_keys) != 0) { | 
					
						
							|  |  |  |         Py_DECREF(sorted_keys); | 
					
						
							|  |  |  |         Py_DECREF(dest); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     num_keys = PyList_GET_SIZE(sorted_keys); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (key_i = 0; key_i < num_keys; key_i++) { | 
					
						
							|  |  |  |         k = PyList_GET_ITEM(sorted_keys, key_i); | 
					
						
							|  |  |  |         v = PyDict_GetItemWithError(src, k); | 
					
						
							|  |  |  |         if (!v) { | 
					
						
							|  |  |  |             if (!PyErr_Occurred()) { | 
					
						
							|  |  |  |                 PyErr_SetObject(PyExc_KeyError, k); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(sorted_keys); | 
					
						
							|  |  |  |             Py_DECREF(dest); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         long vi = PyLong_AsLong(v); | 
					
						
							|  |  |  |         if (vi == -1 && PyErr_Occurred()) { | 
					
						
							|  |  |  |             Py_DECREF(sorted_keys); | 
					
						
							|  |  |  |             Py_DECREF(dest); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (SYMBOL_TO_SCOPE(vi) == scope_type || vi & flag) { | 
					
						
							|  |  |  |             PyObject *item = PyLong_FromSsize_t(i); | 
					
						
							|  |  |  |             if (item == NULL) { | 
					
						
							|  |  |  |                 Py_DECREF(sorted_keys); | 
					
						
							|  |  |  |                 Py_DECREF(dest); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             i++; | 
					
						
							|  |  |  |             if (PyDict_SetItem(dest, k, item) < 0) { | 
					
						
							|  |  |  |                 Py_DECREF(sorted_keys); | 
					
						
							|  |  |  |                 Py_DECREF(item); | 
					
						
							|  |  |  |                 Py_DECREF(dest); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(item); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(sorted_keys); | 
					
						
							|  |  |  |     return dest; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_EnterScope(compiler *c, identifier name, int scope_type, | 
					
						
							|  |  |  |                        void *key, int lineno, PyObject *private, | 
					
						
							|  |  |  |                       _PyCompile_CodeUnitMetadata *umd) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     struct compiler_unit *u; | 
					
						
							|  |  |  |     u = (struct compiler_unit *)PyMem_Calloc(1, sizeof(struct compiler_unit)); | 
					
						
							|  |  |  |     if (!u) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     u->u_scope_type = scope_type; | 
					
						
							|  |  |  |     if (umd != NULL) { | 
					
						
							|  |  |  |         u->u_metadata = *umd; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         u->u_metadata.u_argcount = 0; | 
					
						
							|  |  |  |         u->u_metadata.u_posonlyargcount = 0; | 
					
						
							|  |  |  |         u->u_metadata.u_kwonlyargcount = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     u->u_ste = _PySymtable_Lookup(c->c_st, key); | 
					
						
							|  |  |  |     if (!u->u_ste) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     u->u_metadata.u_name = Py_NewRef(name); | 
					
						
							|  |  |  |     u->u_metadata.u_varnames = list2dict(u->u_ste->ste_varnames); | 
					
						
							|  |  |  |     if (!u->u_metadata.u_varnames) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     u->u_metadata.u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, DEF_COMP_CELL, 0); | 
					
						
							|  |  |  |     if (!u->u_metadata.u_cellvars) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (u->u_ste->ste_needs_class_closure) { | 
					
						
							|  |  |  |         /* Cook up an implicit __class__ cell. */ | 
					
						
							|  |  |  |         Py_ssize_t res; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         assert(u->u_scope_type == COMPILE_SCOPE_CLASS); | 
					
						
							|  |  |  |         res = _PyCompile_DictAddObj(u->u_metadata.u_cellvars, &_Py_ID(__class__)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         if (res < 0) { | 
					
						
							|  |  |  |             compiler_unit_free(u); | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (u->u_ste->ste_needs_classdict) { | 
					
						
							|  |  |  |         /* Cook up an implicit __classdict__ cell. */ | 
					
						
							|  |  |  |         Py_ssize_t res; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         assert(u->u_scope_type == COMPILE_SCOPE_CLASS); | 
					
						
							|  |  |  |         res = _PyCompile_DictAddObj(u->u_metadata.u_cellvars, &_Py_ID(__classdict__)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         if (res < 0) { | 
					
						
							|  |  |  |             compiler_unit_free(u); | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u->u_metadata.u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, | 
					
						
							|  |  |  |                                PyDict_GET_SIZE(u->u_metadata.u_cellvars)); | 
					
						
							|  |  |  |     if (!u->u_metadata.u_freevars) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u->u_metadata.u_fasthidden = PyDict_New(); | 
					
						
							|  |  |  |     if (!u->u_metadata.u_fasthidden) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u->u_nfblocks = 0; | 
					
						
							|  |  |  |     u->u_in_inlined_comp = 0; | 
					
						
							|  |  |  |     u->u_metadata.u_firstlineno = lineno; | 
					
						
							|  |  |  |     u->u_metadata.u_consts = PyDict_New(); | 
					
						
							|  |  |  |     if (!u->u_metadata.u_consts) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     u->u_metadata.u_names = PyDict_New(); | 
					
						
							|  |  |  |     if (!u->u_metadata.u_names) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u->u_deferred_annotations = NULL; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (scope_type == COMPILE_SCOPE_CLASS) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         u->u_static_attributes = PySet_New(0); | 
					
						
							|  |  |  |         if (!u->u_static_attributes) { | 
					
						
							|  |  |  |             compiler_unit_free(u); | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         u->u_static_attributes = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u->u_instr_sequence = (instr_sequence*)_PyInstructionSequence_New(); | 
					
						
							|  |  |  |     if (!u->u_instr_sequence) { | 
					
						
							|  |  |  |         compiler_unit_free(u); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Push the old compiler_unit on the stack. */ | 
					
						
							|  |  |  |     if (c->u) { | 
					
						
							|  |  |  |         PyObject *capsule = PyCapsule_New(c->u, CAPSULE_NAME, NULL); | 
					
						
							|  |  |  |         if (!capsule || PyList_Append(c->c_stack, capsule) < 0) { | 
					
						
							|  |  |  |             Py_XDECREF(capsule); | 
					
						
							|  |  |  |             compiler_unit_free(u); | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(capsule); | 
					
						
							|  |  |  |         if (private == NULL) { | 
					
						
							|  |  |  |             private = c->u->u_private; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     u->u_private = Py_XNewRef(private); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c->u = u; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (scope_type != COMPILE_SCOPE_MODULE) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         RETURN_IF_ERROR(compiler_set_qualname(c)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | void | 
					
						
							|  |  |  | _PyCompile_ExitScope(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     // Don't call PySequence_DelItem() with an exception raised
 | 
					
						
							|  |  |  |     PyObject *exc = PyErr_GetRaisedException(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     instr_sequence *nested_seq = NULL; | 
					
						
							|  |  |  |     if (c->c_save_nested_seqs) { | 
					
						
							|  |  |  |         nested_seq = c->u->u_instr_sequence; | 
					
						
							|  |  |  |         Py_INCREF(nested_seq); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     compiler_unit_free(c->u); | 
					
						
							|  |  |  |     /* Restore c->u to the parent unit. */ | 
					
						
							|  |  |  |     Py_ssize_t n = PyList_GET_SIZE(c->c_stack) - 1; | 
					
						
							|  |  |  |     if (n >= 0) { | 
					
						
							|  |  |  |         PyObject *capsule = PyList_GET_ITEM(c->c_stack, n); | 
					
						
							|  |  |  |         c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME); | 
					
						
							|  |  |  |         assert(c->u); | 
					
						
							|  |  |  |         /* we are deleting from a list so this really shouldn't fail */ | 
					
						
							|  |  |  |         if (PySequence_DelItem(c->c_stack, n) < 0) { | 
					
						
							|  |  |  |             PyErr_FormatUnraisable("Exception ignored on removing " | 
					
						
							|  |  |  |                                    "the last compiler stack item"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (nested_seq != NULL) { | 
					
						
							|  |  |  |             if (_PyInstructionSequence_AddNested(c->u->u_instr_sequence, nested_seq) < 0) { | 
					
						
							|  |  |  |                 PyErr_FormatUnraisable("Exception ignored on appending " | 
					
						
							|  |  |  |                                        "nested instruction sequence"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         c->u = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_XDECREF(nested_seq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyErr_SetRaisedException(exc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Frame block handling functions | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_PushFBlock(compiler *c, location loc, | 
					
						
							|  |  |  |                      fblocktype t, jump_target_label block_label, | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |                      jump_target_label exit, void *datum) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     fblockinfo *f; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     if (c->u->u_nfblocks >= CO_MAXBLOCKS) { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         return _PyCompile_Error(c, loc, "too many statically nested blocks"); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     f = &c->u->u_fblock[c->u->u_nfblocks++]; | 
					
						
							|  |  |  |     f->fb_type = t; | 
					
						
							|  |  |  |     f->fb_block = block_label; | 
					
						
							|  |  |  |     f->fb_loc = loc; | 
					
						
							|  |  |  |     f->fb_exit = exit; | 
					
						
							|  |  |  |     f->fb_datum = datum; | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | void | 
					
						
							|  |  |  | _PyCompile_PopFBlock(compiler *c, fblocktype t, jump_target_label block_label) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     struct compiler_unit *u = c->u; | 
					
						
							|  |  |  |     assert(u->u_nfblocks > 0); | 
					
						
							|  |  |  |     u->u_nfblocks--; | 
					
						
							|  |  |  |     assert(u->u_fblock[u->u_nfblocks].fb_type == t); | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     assert(SAME_JUMP_TARGET_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | fblockinfo * | 
					
						
							|  |  |  | _PyCompile_TopFBlock(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (c->u->u_nfblocks == 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return &c->u->u_fblock[c->u->u_nfblocks - 1]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_DeferredAnnotations(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->u->u_deferred_annotations; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | static location | 
					
						
							|  |  |  | start_location(asdl_stmt_seq *stmts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (asdl_seq_LEN(stmts) > 0) { | 
					
						
							|  |  |  |         /* Set current line number to the line number of first statement.
 | 
					
						
							|  |  |  |          * This way line number for SETUP_ANNOTATIONS will always | 
					
						
							|  |  |  |          * coincide with the line number of first "real" statement in module. | 
					
						
							|  |  |  |          * If body is empty, then lineno will be set later in the assembly stage. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); | 
					
						
							|  |  |  |         return SRC_LOCATION_FROM_AST(st); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (const _Py_SourceLocation){1, 1, 0, 0}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | compiler_codegen(compiler *c, mod_ty mod) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     RETURN_IF_ERROR(_PyCodegen_EnterAnonymousScope(c, mod)); | 
					
						
							|  |  |  |     assert(c->u->u_scope_type == COMPILE_SCOPE_MODULE); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     switch (mod->kind) { | 
					
						
							|  |  |  |     case Module_kind: { | 
					
						
							|  |  |  |         asdl_stmt_seq *stmts = mod->v.Module.body; | 
					
						
							| 
									
										
										
										
											2024-09-13 15:06:06 +01:00
										 |  |  |         RETURN_IF_ERROR(_PyCodegen_Body(c, start_location(stmts), stmts, false)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case Interactive_kind: { | 
					
						
							|  |  |  |         c->c_interactive = 1; | 
					
						
							|  |  |  |         asdl_stmt_seq *stmts = mod->v.Interactive.body; | 
					
						
							| 
									
										
										
										
											2024-09-13 15:06:06 +01:00
										 |  |  |         RETURN_IF_ERROR(_PyCodegen_Body(c, start_location(stmts), stmts, true)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case Expression_kind: { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         RETURN_IF_ERROR(_PyCodegen_Expression(c, mod->v.Expression.body)); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     default: { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  |                      "module kind %d should not be possible", | 
					
						
							|  |  |  |                      mod->kind); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     }} | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyCodeObject * | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | compiler_mod(compiler *c, mod_ty mod) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyCodeObject *co = NULL; | 
					
						
							|  |  |  |     int addNone = mod->kind != Expression_kind; | 
					
						
							|  |  |  |     if (compiler_codegen(c, mod) < 0) { | 
					
						
							|  |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     co = _PyCompile_OptimizeAndAssemble(c, addNone); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | finally: | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     _PyCompile_ExitScope(c); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     return co; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_GetRefType(compiler *c, PyObject *name) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (c->u->u_scope_type == COMPILE_SCOPE_CLASS && | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         (_PyUnicode_EqualToASCIIString(name, "__class__") || | 
					
						
							|  |  |  |          _PyUnicode_EqualToASCIIString(name, "__classdict__"))) { | 
					
						
							|  |  |  |         return CELL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     PySTEntryObject *ste = c->u->u_ste; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     int scope = _PyST_GetScope(ste, name); | 
					
						
							|  |  |  |     if (scope == 0) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  |                      "_PyST_GetScope(name=%R) failed: " | 
					
						
							|  |  |  |                      "unknown scope in unit %S (%R); " | 
					
						
							|  |  |  |                      "symbols: %R; locals: %R; " | 
					
						
							|  |  |  |                      "globals: %R", | 
					
						
							|  |  |  |                      name, | 
					
						
							|  |  |  |                      c->u->u_metadata.u_name, ste->ste_id, | 
					
						
							|  |  |  |                      ste->ste_symbols, c->u->u_metadata.u_varnames, | 
					
						
							|  |  |  |                      c->u->u_metadata.u_names); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return scope; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | dict_lookup_arg(PyObject *dict, PyObject *name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *v = PyDict_GetItemWithError(dict, name); | 
					
						
							|  |  |  |     if (v == NULL) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyLong_AsLong(v); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_LookupCellvar(compiler *c, PyObject *name) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(c->u->u_metadata.u_cellvars); | 
					
						
							|  |  |  |     return dict_lookup_arg(c->u->u_metadata.u_cellvars, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_LookupArg(compiler *c, PyCodeObject *co, PyObject *name) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     /* Special case: If a class contains a method with a
 | 
					
						
							|  |  |  |      * free variable that has the same name as a method, | 
					
						
							|  |  |  |      * the name will be considered free *and* local in the | 
					
						
							|  |  |  |      * class.  It should be handled by the closure, as | 
					
						
							|  |  |  |      * well as by the normal name lookup logic. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     int reftype = _PyCompile_GetRefType(c, name); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     if (reftype == -1) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int arg; | 
					
						
							|  |  |  |     if (reftype == CELL) { | 
					
						
							|  |  |  |         arg = dict_lookup_arg(c->u->u_metadata.u_cellvars, name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         arg = dict_lookup_arg(c->u->u_metadata.u_freevars, name); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (arg == -1 && !PyErr_Occurred()) { | 
					
						
							|  |  |  |         PyObject *freevars = _PyCode_GetFreevars(co); | 
					
						
							|  |  |  |         if (freevars == NULL) { | 
					
						
							|  |  |  |             PyErr_Clear(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  |             "compiler_lookup_arg(name=%R) with reftype=%d failed in %S; " | 
					
						
							|  |  |  |             "freevars of code %S: %R", | 
					
						
							|  |  |  |             name, | 
					
						
							|  |  |  |             reftype, | 
					
						
							|  |  |  |             c->u->u_metadata.u_name, | 
					
						
							|  |  |  |             co->co_name, | 
					
						
							|  |  |  |             freevars); | 
					
						
							| 
									
										
										
										
											2024-11-05 20:34:33 +03:00
										 |  |  |         Py_XDECREF(freevars); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return arg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_StaticAttributesAsTuple(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(c->u->u_static_attributes); | 
					
						
							| 
									
										
										
										
											2024-09-29 01:15:43 +03:00
										 |  |  |     PyObject *static_attributes_unsorted = PySequence_List(c->u->u_static_attributes); | 
					
						
							|  |  |  |     if (static_attributes_unsorted == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyList_Sort(static_attributes_unsorted) != 0) { | 
					
						
							|  |  |  |         Py_DECREF(static_attributes_unsorted); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *static_attributes = PySequence_Tuple(static_attributes_unsorted); | 
					
						
							|  |  |  |     Py_DECREF(static_attributes_unsorted); | 
					
						
							|  |  |  |     return static_attributes; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_ResolveNameop(compiler *c, PyObject *mangled, int scope, | 
					
						
							|  |  |  |                           _PyCompile_optype *optype, Py_ssize_t *arg) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *dict = c->u->u_metadata.u_names; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     *optype = COMPILE_OP_NAME; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     assert(scope >= 0); | 
					
						
							|  |  |  |     switch (scope) { | 
					
						
							|  |  |  |     case FREE: | 
					
						
							|  |  |  |         dict = c->u->u_metadata.u_freevars; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         *optype = COMPILE_OP_DEREF; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case CELL: | 
					
						
							|  |  |  |         dict = c->u->u_metadata.u_cellvars; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         *optype = COMPILE_OP_DEREF; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     case LOCAL: | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (_PyST_IsFunctionLike(c->u->u_ste)) { | 
					
						
							|  |  |  |             *optype = COMPILE_OP_FAST; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             PyObject *item; | 
					
						
							|  |  |  |             RETURN_IF_ERROR(PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, mangled, | 
					
						
							|  |  |  |                                               &item)); | 
					
						
							|  |  |  |             if (item == Py_True) { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |                 *optype = COMPILE_OP_FAST; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |             Py_XDECREF(item); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case GLOBAL_IMPLICIT: | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         if (_PyST_IsFunctionLike(c->u->u_ste)) { | 
					
						
							|  |  |  |             *optype = COMPILE_OP_GLOBAL; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case GLOBAL_EXPLICIT: | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         *optype = COMPILE_OP_GLOBAL; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         /* scope can be 0 */ | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (*optype != COMPILE_OP_FAST) { | 
					
						
							|  |  |  |         *arg = _PyCompile_DictAddObj(dict, mangled); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         RETURN_IF_ERROR(*arg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_TweakInlinedComprehensionScopes(compiler *c, location loc, | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |                                             PySTEntryObject *entry, | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |                                             _PyCompile_InlinedComprehensionState *state) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     int in_class_block = (c->u->u_ste->ste_type == ClassBlock) && !c->u->u_in_inlined_comp; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     c->u->u_in_inlined_comp++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *k, *v; | 
					
						
							|  |  |  |     Py_ssize_t pos = 0; | 
					
						
							|  |  |  |     while (PyDict_Next(entry->ste_symbols, &pos, &k, &v)) { | 
					
						
							|  |  |  |         long symbol = PyLong_AsLong(v); | 
					
						
							|  |  |  |         assert(symbol >= 0 || PyErr_Occurred()); | 
					
						
							|  |  |  |         RETURN_IF_ERROR(symbol); | 
					
						
							|  |  |  |         long scope = SYMBOL_TO_SCOPE(symbol); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |         long outsymbol = _PyST_GetSymbol(c->u->u_ste, k); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |         RETURN_IF_ERROR(outsymbol); | 
					
						
							|  |  |  |         long outsc = SYMBOL_TO_SCOPE(outsymbol); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If a name has different scope inside than outside the comprehension,
 | 
					
						
							|  |  |  |         // we need to temporarily handle it with the right scope while
 | 
					
						
							|  |  |  |         // compiling the comprehension. If it's free in the comprehension
 | 
					
						
							|  |  |  |         // scope, no special handling; it should be handled the same as the
 | 
					
						
							|  |  |  |         // enclosing scope. (If it's free in outer scope and cell in inner
 | 
					
						
							|  |  |  |         // scope, we can't treat it as both cell and free in the same function,
 | 
					
						
							|  |  |  |         // but treating it as free throughout is fine; it's *_DEREF
 | 
					
						
							|  |  |  |         // either way.)
 | 
					
						
							|  |  |  |         if ((scope != outsc && scope != FREE && !(scope == CELL && outsc == FREE)) | 
					
						
							|  |  |  |                 || in_class_block) { | 
					
						
							|  |  |  |             if (state->temp_symbols == NULL) { | 
					
						
							|  |  |  |                 state->temp_symbols = PyDict_New(); | 
					
						
							|  |  |  |                 if (state->temp_symbols == NULL) { | 
					
						
							|  |  |  |                     return ERROR; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             // update the symbol to the in-comprehension version and save
 | 
					
						
							|  |  |  |             // the outer version; we'll restore it after running the
 | 
					
						
							|  |  |  |             // comprehension
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |             if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v) < 0) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |                 return ERROR; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             PyObject *outv = PyLong_FromLong(outsymbol); | 
					
						
							|  |  |  |             if (outv == NULL) { | 
					
						
							|  |  |  |                 return ERROR; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             int res = PyDict_SetItem(state->temp_symbols, k, outv); | 
					
						
							|  |  |  |             Py_DECREF(outv); | 
					
						
							|  |  |  |             RETURN_IF_ERROR(res); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // locals handling for names bound in comprehension (DEF_LOCAL |
 | 
					
						
							|  |  |  |         // DEF_NONLOCAL occurs in assignment expression to nonlocal)
 | 
					
						
							|  |  |  |         if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL)) || in_class_block) { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |             if (!_PyST_IsFunctionLike(c->u->u_ste)) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |                 // non-function scope: override this name to use fast locals
 | 
					
						
							|  |  |  |                 PyObject *orig; | 
					
						
							|  |  |  |                 if (PyDict_GetItemRef(c->u->u_metadata.u_fasthidden, k, &orig) < 0) { | 
					
						
							|  |  |  |                     return ERROR; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 assert(orig == NULL || orig == Py_True || orig == Py_False); | 
					
						
							|  |  |  |                 if (orig != Py_True) { | 
					
						
							|  |  |  |                     if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_True) < 0) { | 
					
						
							|  |  |  |                         return ERROR; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (state->fast_hidden == NULL) { | 
					
						
							|  |  |  |                         state->fast_hidden = PySet_New(NULL); | 
					
						
							|  |  |  |                         if (state->fast_hidden == NULL) { | 
					
						
							|  |  |  |                             return ERROR; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (PySet_Add(state->fast_hidden, k) < 0) { | 
					
						
							|  |  |  |                         return ERROR; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_RevertInlinedComprehensionScopes(compiler *c, location loc, | 
					
						
							|  |  |  |                                              _PyCompile_InlinedComprehensionState *state) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-09-02 18:23:39 +01:00
										 |  |  |     c->u->u_in_inlined_comp--; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     if (state->temp_symbols) { | 
					
						
							|  |  |  |         PyObject *k, *v; | 
					
						
							|  |  |  |         Py_ssize_t pos = 0; | 
					
						
							|  |  |  |         while (PyDict_Next(state->temp_symbols, &pos, &k, &v)) { | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |             if (PyDict_SetItem(c->u->u_ste->ste_symbols, k, v)) { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |                 return ERROR; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_CLEAR(state->temp_symbols); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (state->fast_hidden) { | 
					
						
							|  |  |  |         while (PySet_Size(state->fast_hidden) > 0) { | 
					
						
							|  |  |  |             PyObject *k = PySet_Pop(state->fast_hidden); | 
					
						
							|  |  |  |             if (k == NULL) { | 
					
						
							|  |  |  |                 return ERROR; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             // we set to False instead of clearing, so we can track which names
 | 
					
						
							|  |  |  |             // were temporarily fast-locals and should use CO_FAST_HIDDEN
 | 
					
						
							|  |  |  |             if (PyDict_SetItem(c->u->u_metadata.u_fasthidden, k, Py_False)) { | 
					
						
							|  |  |  |                 Py_DECREF(k); | 
					
						
							|  |  |  |                 return ERROR; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(k); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_CLEAR(state->fast_hidden); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_AddDeferredAnnotaion(compiler *c, stmt_ty s) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (c->u->u_deferred_annotations == NULL) { | 
					
						
							|  |  |  |         c->u->u_deferred_annotations = PyList_New(0); | 
					
						
							|  |  |  |         if (c->u->u_deferred_annotations == NULL) { | 
					
						
							|  |  |  |             return ERROR; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     PyObject *ptr = PyLong_FromVoidPtr((void *)s); | 
					
						
							|  |  |  |     if (ptr == NULL) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyList_Append(c->u->u_deferred_annotations, ptr) < 0) { | 
					
						
							|  |  |  |         Py_DECREF(ptr); | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     Py_DECREF(ptr); | 
					
						
							|  |  |  |     return SUCCESS; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Raises a SyntaxError and returns ERROR.
 | 
					
						
							|  |  |  |  * If something goes wrong, a different exception may be raised. | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | _PyCompile_Error(compiler *c, location loc, const char *format, ...) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     va_list vargs; | 
					
						
							|  |  |  |     va_start(vargs, format); | 
					
						
							|  |  |  |     PyObject *msg = PyUnicode_FromFormatV(format, vargs); | 
					
						
							|  |  |  |     va_end(vargs); | 
					
						
							|  |  |  |     if (msg == NULL) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-16 15:05:00 +01:00
										 |  |  |     _PyErr_RaiseSyntaxError(msg, c->c_filename, loc.lineno, loc.col_offset + 1, | 
					
						
							|  |  |  |                             loc.end_lineno, loc.end_col_offset + 1); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     Py_DECREF(msg); | 
					
						
							|  |  |  |     return ERROR; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-16 15:05:00 +01:00
										 |  |  | /* Emits a SyntaxWarning and returns 0 on success.
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |    If a SyntaxWarning raised as error, replaces it with a SyntaxError | 
					
						
							| 
									
										
										
										
											2024-09-16 15:05:00 +01:00
										 |  |  |    and returns -1. | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | */ | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_Warn(compiler *c, location loc, const char *format, ...) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     va_list vargs; | 
					
						
							|  |  |  |     va_start(vargs, format); | 
					
						
							|  |  |  |     PyObject *msg = PyUnicode_FromFormatV(format, vargs); | 
					
						
							|  |  |  |     va_end(vargs); | 
					
						
							|  |  |  |     if (msg == NULL) { | 
					
						
							|  |  |  |         return ERROR; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-09-16 15:05:00 +01:00
										 |  |  |     int ret = _PyErr_EmitSyntaxWarning(msg, c->c_filename, loc.lineno, loc.col_offset + 1, | 
					
						
							|  |  |  |                                        loc.end_lineno, loc.end_col_offset + 1); | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     Py_DECREF(msg); | 
					
						
							| 
									
										
										
										
											2024-09-16 15:05:00 +01:00
										 |  |  |     return ret; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_Mangle(compiler *c, PyObject *name) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _Py_Mangle(c->u->u_private, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_MaybeMangle(compiler *c, PyObject *name) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return _Py_MaybeMangle(c->u->u_private, c->u->u_ste, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | instr_sequence * | 
					
						
							|  |  |  | _PyCompile_InstrSequence(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->u->u_instr_sequence; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_FutureFeatures(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->c_future.ff_features; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | struct symtable * | 
					
						
							|  |  |  | _PyCompile_Symtable(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->c_st; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PySTEntryObject * | 
					
						
							|  |  |  | _PyCompile_SymtableEntry(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->u->u_ste; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_OptimizationLevel(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->c_optimize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2024-09-16 14:58:18 +01:00
										 |  |  | _PyCompile_IsInteractiveTopLevel(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(c->c_stack != NULL); | 
					
						
							|  |  |  |     assert(PyList_CheckExact(c->c_stack)); | 
					
						
							| 
									
										
										
										
											2024-09-16 14:58:18 +01:00
										 |  |  |     bool is_nested_scope = PyList_GET_SIZE(c->c_stack) > 0; | 
					
						
							|  |  |  |     return c->c_interactive && !is_nested_scope; | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_ScopeType(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-23 10:39:42 +01:00
										 |  |  |     return c->u->u_scope_type; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_IsInInlinedComp(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-27 16:57:31 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return c->u->u_in_inlined_comp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_Qualname(compiler *c) | 
					
						
							| 
									
										
										
										
											2024-08-23 19:53:15 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     assert(c->u->u_metadata.u_qualname); | 
					
						
							|  |  |  |     return c->u->u_metadata.u_qualname; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | _PyCompile_CodeUnitMetadata * | 
					
						
							|  |  |  | _PyCompile_Metadata(compiler *c) | 
					
						
							| 
									
										
										
										
											2021-10-06 13:05:45 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     return &c->u->u_metadata; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-07-10 17:09:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-10 11:34:54 +01:00
										 |  |  | // Merge *obj* with constant cache, without recursion.
 | 
					
						
							| 
									
										
										
										
											2023-03-31 18:17:59 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj) | 
					
						
							| 
									
										
										
										
											2018-11-26 21:23:22 +09:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-07-10 11:34:54 +01:00
										 |  |  |     PyObject *key = const_cache_insert(const_cache, *obj, false); | 
					
						
							| 
									
										
										
										
											2018-11-26 21:23:22 +09:00
										 |  |  |     if (key == NULL) { | 
					
						
							| 
									
										
										
										
											2023-01-31 00:06:19 +00:00
										 |  |  |         return ERROR; | 
					
						
							| 
									
										
										
										
											2018-11-26 21:23:22 +09:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-07-10 11:34:54 +01:00
										 |  |  |     if (PyTuple_CheckExact(key)) { | 
					
						
							|  |  |  |         PyObject *item = PyTuple_GET_ITEM(key, 1); | 
					
						
							| 
									
										
										
										
											2024-02-07 13:43:18 -05:00
										 |  |  |         Py_SETREF(*obj, Py_NewRef(item)); | 
					
						
							| 
									
										
										
										
											2024-07-10 11:34:54 +01:00
										 |  |  |         Py_DECREF(key); | 
					
						
							| 
									
										
										
										
											2024-02-07 13:43:18 -05:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2024-07-10 11:34:54 +01:00
										 |  |  |         Py_SETREF(*obj, key); | 
					
						
							| 
									
										
										
										
											2021-02-10 09:20:42 +09:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-01-31 00:06:19 +00:00
										 |  |  |     return SUCCESS; | 
					
						
							| 
									
										
										
										
											2018-11-26 21:23:22 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | consts_dict_keys_inorder(PyObject *dict) | 
					
						
							| 
									
										
										
										
											2022-12-12 14:22:15 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     PyObject *consts, *k, *v; | 
					
						
							|  |  |  |     Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     consts = PyList_New(size);   /* PyCode_Optimize() requires a list */ | 
					
						
							|  |  |  |     if (consts == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     while (PyDict_Next(dict, &pos, &k, &v)) { | 
					
						
							|  |  |  |         assert(PyLong_CheckExact(v)); | 
					
						
							|  |  |  |         i = PyLong_AsLong(v); | 
					
						
							|  |  |  |         /* The keys of the dictionary can be tuples wrapping a constant.
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |          * (see _PyCompile_DictAddObj and _PyCode_ConstantKey). In that case | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |          * the object we want is always second. */ | 
					
						
							|  |  |  |         if (PyTuple_CheckExact(k)) { | 
					
						
							|  |  |  |             k = PyTuple_GET_ITEM(k, 1); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         assert(i < size); | 
					
						
							|  |  |  |         assert(i >= 0); | 
					
						
							|  |  |  |         PyList_SET_ITEM(consts, i, Py_NewRef(k)); | 
					
						
							| 
									
										
										
										
											2022-12-12 14:22:15 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  |     return consts; | 
					
						
							| 
									
										
										
										
											2022-12-12 14:22:15 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | static int | 
					
						
							|  |  |  | compute_code_flags(compiler *c) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PySTEntryObject *ste = c->u->u_ste; | 
					
						
							|  |  |  |     int flags = 0; | 
					
						
							|  |  |  |     if (_PyST_IsFunctionLike(ste)) { | 
					
						
							|  |  |  |         flags |= CO_NEWLOCALS | CO_OPTIMIZED; | 
					
						
							|  |  |  |         if (ste->ste_nested) | 
					
						
							|  |  |  |             flags |= CO_NESTED; | 
					
						
							|  |  |  |         if (ste->ste_generator && !ste->ste_coroutine) | 
					
						
							|  |  |  |             flags |= CO_GENERATOR; | 
					
						
							|  |  |  |         if (ste->ste_generator && ste->ste_coroutine) | 
					
						
							|  |  |  |             flags |= CO_ASYNC_GENERATOR; | 
					
						
							|  |  |  |         if (ste->ste_varargs) | 
					
						
							|  |  |  |             flags |= CO_VARARGS; | 
					
						
							|  |  |  |         if (ste->ste_varkeywords) | 
					
						
							|  |  |  |             flags |= CO_VARKEYWORDS; | 
					
						
							| 
									
										
										
										
											2024-10-30 17:01:09 +08:00
										 |  |  |         if (ste->ste_has_docstring) | 
					
						
							|  |  |  |             flags |= CO_HAS_DOCSTRING; | 
					
						
							| 
									
										
										
										
											2024-12-19 13:03:14 -08:00
										 |  |  |         if (ste->ste_method) | 
					
						
							|  |  |  |             flags |= CO_METHOD; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ste->ste_coroutine && !ste->ste_generator) { | 
					
						
							|  |  |  |         flags |= CO_COROUTINE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* (Only) inherit compilerflags in PyCF_MASK */ | 
					
						
							|  |  |  |     flags |= (c->c_flags.cf_flags & PyCF_MASK); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return flags; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  | static PyCodeObject * | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  | optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache, | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |                                 int code_flags, PyObject *filename) | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     cfg_builder *g = NULL; | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |     instr_sequence optimized_instrs; | 
					
						
							|  |  |  |     memset(&optimized_instrs, 0, sizeof(instr_sequence)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  |     PyCodeObject *co = NULL; | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |     PyObject *consts = consts_dict_keys_inorder(u->u_metadata.u_consts); | 
					
						
							| 
									
										
										
										
											2022-10-05 08:52:35 +01:00
										 |  |  |     if (consts == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-05-30 21:55:06 +01:00
										 |  |  |     g = _PyCfg_FromInstructionSequence(u->u_instr_sequence); | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     if (g == NULL) { | 
					
						
							| 
									
										
										
										
											2021-09-02 20:02:06 +09:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |     int nlocals = (int)PyDict_GET_SIZE(u->u_metadata.u_varnames); | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     int nparams = (int)PyList_GET_SIZE(u->u_ste->ste_varnames); | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |     assert(u->u_metadata.u_firstlineno); | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (_PyCfg_OptimizeCodeUnit(g, consts, const_cache, nlocals, | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |                                 nparams, u->u_metadata.u_firstlineno) < 0) { | 
					
						
							| 
									
										
										
										
											2022-11-11 10:53:43 +00:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-10-05 08:52:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     int stackdepth; | 
					
						
							|  |  |  |     int nlocalsplus; | 
					
						
							|  |  |  |     if (_PyCfg_OptimizedCfgToInstructionSequence(g, &u->u_metadata, code_flags, | 
					
						
							|  |  |  |                                                  &stackdepth, &nlocalsplus, | 
					
						
							|  |  |  |                                                  &optimized_instrs) < 0) { | 
					
						
							| 
									
										
										
										
											2022-11-30 12:37:30 +00:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-26 13:32:47 +01:00
										 |  |  |     /** Assembly **/ | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |     co = _PyAssemble_MakeCodeObject(&u->u_metadata, const_cache, consts, | 
					
						
							| 
									
										
										
										
											2023-07-26 13:32:47 +01:00
										 |  |  |                                     stackdepth, &optimized_instrs, nlocalsplus, | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |                                     code_flags, filename); | 
					
						
							| 
									
										
										
										
											2021-05-07 15:19:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-24 12:30:49 -06:00
										 |  |  | error: | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  |     Py_XDECREF(consts); | 
					
						
							| 
									
										
										
										
											2024-04-04 16:47:26 +01:00
										 |  |  |     PyInstructionSequence_Fini(&optimized_instrs); | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     _PyCfgBuilder_Free(g); | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  |     return co; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-04-21 16:10:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-30 22:54:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyCodeObject * | 
					
						
							|  |  |  | _PyCompile_OptimizeAndAssemble(compiler *c, int addNone) | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     struct compiler_unit *u = c->u; | 
					
						
							|  |  |  |     PyObject *const_cache = c->c_const_cache; | 
					
						
							|  |  |  |     PyObject *filename = c->c_filename; | 
					
						
							| 
									
										
										
										
											2022-04-21 16:10:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  |     int code_flags = compute_code_flags(c); | 
					
						
							|  |  |  |     if (code_flags < 0) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2022-03-01 10:27:20 +09:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-04-21 16:10:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (_PyCodegen_AddReturnAtEnd(c, addNone) < 0) { | 
					
						
							| 
									
										
										
										
											2023-03-13 15:59:20 +00:00
										 |  |  |         return NULL; | 
					
						
							| 
									
										
										
										
											2021-02-10 09:20:42 +09:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-05-09 15:52:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-11 11:15:09 +01:00
										 |  |  |     return optimize_and_assemble_code_unit(u, const_cache, code_flags, filename); | 
					
						
							| 
									
										
										
										
											2001-01-19 03:21:30 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-12-04 10:26:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  | PyCodeObject * | 
					
						
							|  |  |  | _PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags, | 
					
						
							|  |  |  |                int optimize, PyArena *arena) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  |     compiler *c = new_compiler(mod, filename, pflags, optimize, arena); | 
					
						
							|  |  |  |     if (c == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyCodeObject *co = compiler_mod(c, mod); | 
					
						
							|  |  |  |     compiler_free(c); | 
					
						
							|  |  |  |     assert(co || PyErr_Occurred()); | 
					
						
							|  |  |  |     return co; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | _PyCompile_AstOptimize(mod_ty mod, PyObject *filename, PyCompilerFlags *cf, | 
					
						
							|  |  |  |                        int optimize, PyArena *arena) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     _PyFutureFeatures future; | 
					
						
							|  |  |  |     if (!_PyFuture_FromAST(mod, filename, &future)) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int flags = future.ff_features | cf->cf_flags; | 
					
						
							|  |  |  |     if (optimize == -1) { | 
					
						
							|  |  |  |         optimize = _Py_GetConfig()->optimization_level; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!_PyAST_Optimize(mod, arena, optimize, flags)) { | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 19:33:32 +09:00
										 |  |  | // C implementation of inspect.cleandoc()
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Difference from inspect.cleandoc():
 | 
					
						
							|  |  |  | // - Do not remove leading and trailing blank lines to keep lineno.
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_CleanDoc(PyObject *doc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     doc = PyObject_CallMethod(doc, "expandtabs", NULL); | 
					
						
							|  |  |  |     if (doc == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_ssize_t doc_size; | 
					
						
							|  |  |  |     const char *doc_utf8 = PyUnicode_AsUTF8AndSize(doc, &doc_size); | 
					
						
							|  |  |  |     if (doc_utf8 == NULL) { | 
					
						
							|  |  |  |         Py_DECREF(doc); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const char *p = doc_utf8; | 
					
						
							|  |  |  |     const char *pend = p + doc_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // First pass: find minimum indentation of any non-blank lines
 | 
					
						
							|  |  |  |     // after first line.
 | 
					
						
							|  |  |  |     while (p < pend && *p++ != '\n') { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_ssize_t margin = PY_SSIZE_T_MAX; | 
					
						
							|  |  |  |     while (p < pend) { | 
					
						
							|  |  |  |         const char *s = p; | 
					
						
							|  |  |  |         while (*p == ' ') p++; | 
					
						
							|  |  |  |         if (p < pend && *p != '\n') { | 
					
						
							|  |  |  |             margin = Py_MIN(margin, p - s); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         while (p < pend && *p++ != '\n') { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (margin == PY_SSIZE_T_MAX) { | 
					
						
							|  |  |  |         margin = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Second pass: write cleandoc into buff.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // copy first line without leading spaces.
 | 
					
						
							|  |  |  |     p = doc_utf8; | 
					
						
							|  |  |  |     while (*p == ' ') { | 
					
						
							|  |  |  |         p++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (p == doc_utf8 && margin == 0 ) { | 
					
						
							|  |  |  |         // doc is already clean.
 | 
					
						
							|  |  |  |         return doc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     char *buff = PyMem_Malloc(doc_size); | 
					
						
							| 
									
										
										
										
											2023-07-21 07:56:58 +03:00
										 |  |  |     if (buff == NULL){ | 
					
						
							|  |  |  |         Py_DECREF(doc); | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 19:33:32 +09:00
										 |  |  |     char *w = buff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (p < pend) { | 
					
						
							|  |  |  |         int ch = *w++ = *p++; | 
					
						
							|  |  |  |         if (ch == '\n') { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // copy subsequent lines without margin.
 | 
					
						
							|  |  |  |     while (p < pend) { | 
					
						
							|  |  |  |         for (Py_ssize_t i = 0; i < margin; i++, p++) { | 
					
						
							|  |  |  |             if (*p != ' ') { | 
					
						
							|  |  |  |                 assert(*p == '\n' || *p == '\0'); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         while (p < pend) { | 
					
						
							|  |  |  |             int ch = *w++ = *p++; | 
					
						
							|  |  |  |             if (ch == '\n') { | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(doc); | 
					
						
							| 
									
										
										
										
											2023-07-18 12:44:16 +09:00
										 |  |  |     PyObject *res = PyUnicode_FromStringAndSize(buff, w - buff); | 
					
						
							|  |  |  |     PyMem_Free(buff); | 
					
						
							|  |  |  |     return res; | 
					
						
							| 
									
										
										
										
											2023-07-15 19:33:32 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 21:55:06 +01:00
										 |  |  | /* Access to compiler optimizations for unit tests.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * _PyCompile_CodeGen takes an AST, applies code-gen and | 
					
						
							|  |  |  |  * returns the unoptimized CFG as an instruction list. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | _PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags, | 
					
						
							| 
									
										
										
										
											2023-05-07 18:47:28 +01:00
										 |  |  |                    int optimize, int compile_mode) | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *res = NULL; | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  |     PyObject *metadata = NULL; | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!PyAST_Check(ast)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, "expected an AST"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyArena *arena = _PyArena_New(); | 
					
						
							|  |  |  |     if (arena == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 18:47:28 +01:00
										 |  |  |     mod_ty mod = PyAST_obj2mod(ast, arena, compile_mode); | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |     if (mod == NULL || !_PyAST_Validate(mod)) { | 
					
						
							|  |  |  |         _PyArena_Free(arena); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     compiler *c = new_compiler(mod, filename, pflags, optimize, arena); | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |     if (c == NULL) { | 
					
						
							|  |  |  |         _PyArena_Free(arena); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-24 10:46:17 +01:00
										 |  |  |     c->c_save_nested_seqs = true; | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-15 14:32:21 +00:00
										 |  |  |     metadata = PyDict_New(); | 
					
						
							|  |  |  |     if (metadata == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-12 14:22:15 +00:00
										 |  |  |     if (compiler_codegen(c, mod) < 0) { | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |         goto finally; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     _PyCompile_CodeUnitMetadata *umd = &c->u->u_metadata; | 
					
						
							| 
									
										
										
										
											2024-02-15 14:32:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-08 15:18:28 +03:00
										 |  |  | #define SET_METADATA_INT(key, value) do { \
 | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  |         PyObject *v = PyLong_FromLong((long)value); \ | 
					
						
							|  |  |  |         if (v == NULL) goto finally; \ | 
					
						
							|  |  |  |         int res = PyDict_SetItemString(metadata, key, v); \ | 
					
						
							|  |  |  |         Py_XDECREF(v); \ | 
					
						
							|  |  |  |         if (res < 0) goto finally; \ | 
					
						
							|  |  |  |     } while (0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-08 15:18:28 +03:00
										 |  |  |     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
 | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-07 18:47:28 +01:00
										 |  |  |     int addNone = mod->kind != Expression_kind; | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (_PyCodegen_AddReturnAtEnd(c, addNone) < 0) { | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  |         goto finally; | 
					
						
							| 
									
										
										
										
											2023-05-07 18:47:28 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     if (_PyInstructionSequence_ApplyLabelMap(_PyCompile_InstrSequence(c)) < 0) { | 
					
						
							| 
									
										
										
										
											2024-03-27 17:38:19 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-04-17 16:42:04 +01:00
										 |  |  |     /* Allocate a copy of the instruction sequence on the heap */ | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     res = PyTuple_Pack(2, _PyCompile_InstrSequence(c), metadata); | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | finally: | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  |     Py_XDECREF(metadata); | 
					
						
							| 
									
										
										
										
											2024-09-09 18:21:51 +01:00
										 |  |  |     _PyCompile_ExitScope(c); | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |     compiler_free(c); | 
					
						
							|  |  |  |     _PyArena_Free(arena); | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-08-24 11:02:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  | int _PyCfg_JumpLabelsToTargets(cfg_builder *g); | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyCodeObject * | 
					
						
							|  |  |  | _PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename, | 
					
						
							| 
									
										
										
										
											2024-04-17 16:42:04 +01:00
										 |  |  |                     PyObject *seq) | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2024-04-17 16:42:04 +01:00
										 |  |  |     if (!_PyInstructionSequence_Check(seq)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, "expected an instruction sequence"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     cfg_builder *g = NULL; | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |     PyCodeObject *co = NULL; | 
					
						
							|  |  |  |     instr_sequence optimized_instrs; | 
					
						
							|  |  |  |     memset(&optimized_instrs, 0, sizeof(instr_sequence)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyObject *const_cache = PyDict_New(); | 
					
						
							|  |  |  |     if (const_cache == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-30 21:55:06 +01:00
										 |  |  |     g = _PyCfg_FromInstructionSequence((instr_sequence*)seq); | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     if (g == NULL) { | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     if (_PyCfg_JumpLabelsToTargets(g) < 0) { | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-26 13:32:47 +01:00
										 |  |  |     int code_flags = 0; | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     int stackdepth, nlocalsplus; | 
					
						
							|  |  |  |     if (_PyCfg_OptimizedCfgToInstructionSequence(g, umd, code_flags, | 
					
						
							|  |  |  |                                                  &stackdepth, &nlocalsplus, | 
					
						
							|  |  |  |                                                  &optimized_instrs) < 0) { | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  |     PyObject *consts = consts_dict_keys_inorder(umd->u_consts); | 
					
						
							|  |  |  |     if (consts == NULL) { | 
					
						
							|  |  |  |         goto error; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |     co = _PyAssemble_MakeCodeObject(umd, const_cache, | 
					
						
							| 
									
										
										
										
											2023-07-26 13:32:47 +01:00
										 |  |  |                                     consts, stackdepth, &optimized_instrs, | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |                                     nlocalsplus, code_flags, filename); | 
					
						
							| 
									
										
										
										
											2023-05-09 14:33:40 +01:00
										 |  |  |     Py_DECREF(consts); | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |     Py_DECREF(const_cache); | 
					
						
							| 
									
										
										
										
											2023-08-10 13:03:47 +01:00
										 |  |  |     _PyCfgBuilder_Free(g); | 
					
						
							| 
									
										
										
										
											2024-04-04 16:47:26 +01:00
										 |  |  |     PyInstructionSequence_Fini(&optimized_instrs); | 
					
						
							| 
									
										
										
										
											2023-05-01 22:29:30 +01:00
										 |  |  |     return co; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 10:03:00 +01:00
										 |  |  | /* Retained for API compatibility.
 | 
					
						
							| 
									
										
										
										
											2023-03-31 18:17:59 +01:00
										 |  |  |  * Optimization is now done in _PyCfg_OptimizeCodeUnit */ | 
					
						
							| 
									
										
										
										
											2020-07-30 10:03:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyCode_Optimize(PyObject *code, PyObject* Py_UNUSED(consts), | 
					
						
							|  |  |  |                 PyObject *Py_UNUSED(names), PyObject *Py_UNUSED(lnotab_obj)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-11-10 11:23:36 +01:00
										 |  |  |     return Py_NewRef(code); | 
					
						
							| 
									
										
										
										
											2020-07-30 10:03:00 +01:00
										 |  |  | } |