cpython/Python/compile.c

/*
 * This file compiles an abstract syntax tree (AST) into Python bytecode.
 *
 * The primary entry point is _PyAST_Compile(), which returns a
 * PyCodeObject.  The compiler makes several passes to build the code
 * object:
 *   1. Checks for future statements.  See future.c
 *   2. Builds a symbol table.  See symtable.c.
 *   3. Generate an instruction sequence. See compiler_mod() in this file.
 *   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.
 *
 * Note that compiler_mod() suggests module, but the module ast type
 * (mod_ty) has cases for expressions and interactive statements.
 *
 * CAUTION: The VISIT_* macros abort the current function when they
 * encounter a problem. So don't invoke them when there is memory
 * which needs to be released. Code blocks are OK, as the compiler
 * structure takes care of releasing those.  Use the arena to manage
 * objects.
 */

#include <stdbool.h>

#include "Python.h"
#include "opcode.h"
#include "pycore_ast.h"           // _PyAST_GetDocString()
#define NEED_OPCODE_TABLES
#include "pycore_opcode_utils.h"
#undef NEED_OPCODE_TABLES
#include "pycore_code.h"          // _PyCode_New()
#include "pycore_compile.h"
#include "pycore_flowgraph.h"
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
#include "pycore_intrinsics.h"
#include "pycore_long.h"          // _PyLong_GetZero()
#include "pycore_pystate.h"       // _Py_GetConfig()
#include "pycore_setobject.h"     // _PySet_NextEntry()
#include "pycore_symtable.h"      // PySTEntryObject, _PyFuture_FromAST()

#define NEED_OPCODE_METADATA
#include "pycore_opcode_metadata.h" // _PyOpcode_opcode_metadata, _PyOpcode_num_popped/pushed
#undef NEED_OPCODE_METADATA

#define COMP_GENEXP
#define COMP_LISTCOMP
#define COMP_SETCOMP
#define COMP_DICTCOMP

/* A soft limit for stack use, to avoid excessive
 * memory use for large constants, etc.
 *
 * The value 30 is plucked out of thin air.
 * Code that could use more stack than this is
 * rare, so the exact value is unimportant.
 */
#define STACK_USE_GUIDELINE

#undef SUCCESS
#undef ERROR
#define SUCCESS
#define ERROR

#define RETURN_IF_ERROR(X)

#define RETURN_IF_ERROR_IN_SCOPE(C, CALL)

struct compiler;

instruction;
instr_sequence;

static instr_sequence *compiler_instr_sequence(struct compiler *c);
static int compiler_future_features(struct compiler *c);
static struct symtable *compiler_symtable(struct compiler *c);
static PySTEntryObject *compiler_symtable_entry(struct compiler *c);

#define IS_TOP_LEVEL_AWAIT(C)
#define INSTR_SEQUENCE(C)
#define FUTURE_FEATURES(C)
#define SYMTABLE(C)
#define SYMTABLE_ENTRY(C)
#define OPTIMIZATION_LEVEL(C)
#define IS_INTERACTIVE(C)
#define IS_NESTED_SCOPE(C)
#define SCOPE_TYPE(C)
#define QUALNAME(C)
#define METADATA(C)
#define ARENA(C)

location;
cfg_builder;
jump_target_label;

enum fblocktype;

#ifndef NDEBUG
static int compiler_is_top_level_await(struct compiler *c);
#endif
static PyObject *compiler_mangle(struct compiler *c, PyObject *name);
static PyObject *compiler_maybe_mangle(struct compiler *c, PyObject *name);
static int compiler_optimization_level(struct compiler *c);
static int compiler_is_interactive(struct compiler *c);
static int compiler_is_nested_scope(struct compiler *c);
static int compiler_scope_type(struct compiler *c);
static int compiler_is_in_inlined_comp(struct compiler *c);
static PyObject *compiler_qualname(struct compiler *c);
static PyObject *compiler_static_attributes_tuple(struct compiler *c);
static int compiler_lookup_arg(struct compiler *c, PyCodeObject *co, PyObject *name);
static int compiler_get_ref_type(struct compiler *c, PyObject *name);
static int compiler_lookup_cellvar(struct compiler *c, PyObject *name);
static PyObject *compiler_deferred_annotations(struct compiler *c);
static int compiler_push_fblock(struct compiler *c, location loc,
                                enum fblocktype t, jump_target_label block_label,
                                jump_target_label exit, void *datum);
static void compiler_pop_fblock(struct compiler *c, enum fblocktype t,
                                jump_target_label block_label);
static struct fblockinfo *compiler_top_fblock(struct compiler *c);
static int compiler_enter_scope(struct compiler *c, identifier name, int scope_type,
                                void *key, int lineno, PyObject *private,
                               _PyCompile_CodeUnitMetadata *umd);
static void compiler_exit_scope(struct compiler *c);
static Py_ssize_t compiler_add_const(struct compiler *c, PyObject *o);
static int compiler_maybe_add_static_attribute_to_class(struct compiler *c, expr_ty e);
static _PyCompile_CodeUnitMetadata *compiler_unit_metadata(struct compiler *c);
static PyArena *compiler_arena(struct compiler *c);

#define LOCATION(LNO, END_LNO, COL, END_COL)

#define LOC(x)

static jump_target_label NO_LABEL =;

#define SAME_LABEL(L1, L2)
#define IS_LABEL(L)

#define NEW_JUMP_TARGET_LABEL(C, NAME)

#define USE_LABEL(C, LBL)


/* fblockinfo tracks the current frame block.

A frame block is used to handle loops, try/except, and try/finally.
It's called a frame block to distinguish it from a basic block in the
compiler IR.
*/

enum fblocktype {};

struct fblockinfo {};

enum {};


static const int compare_masks[] =;

/*
 * Resize the array if index is out of range.
 *
 * idx: the index we want to access
 * arr: pointer to the array
 * alloc: pointer to the capacity of the array
 * default_alloc: initial number of items
 * item_size: size of each item
 *
 */
int
_PyCompile_EnsureArrayLargeEnough(int idx, void **array, int *alloc,
                                  int default_alloc, size_t item_size)
{}


pattern_context;

static void compiler_free(struct compiler *);
static int compiler_error(struct compiler *, location loc, const char *, ...);
static int compiler_warn(struct compiler *, location loc, const char *, ...);
static int codegen_nameop(struct compiler *, location, identifier, expr_context_ty);

static PyCodeObject *compiler_mod(struct compiler *, mod_ty);
static int codegen_visit_stmt(struct compiler *, stmt_ty);
static int codegen_visit_keyword(struct compiler *, keyword_ty);
static int codegen_visit_expr(struct compiler *, expr_ty);
static int codegen_augassign(struct compiler *, stmt_ty);
static int codegen_annassign(struct compiler *, stmt_ty);
static int codegen_subscript(struct compiler *, expr_ty);
static int codegen_slice(struct compiler *, expr_ty);

static bool are_all_items_const(asdl_expr_seq *, Py_ssize_t, Py_ssize_t);


static int codegen_with(struct compiler *, stmt_ty, int);
static int codegen_async_with(struct compiler *, stmt_ty, int);
static int codegen_async_for(struct compiler *, stmt_ty);
static int codegen_call_simple_kw_helper(struct compiler *c,
                                         location loc,
                                         asdl_keyword_seq *keywords,
                                         Py_ssize_t nkwelts);
static int codegen_call_helper(struct compiler *c, location loc,
                               int n, asdl_expr_seq *args,
                               asdl_keyword_seq *keywords);
static int codegen_try_except(struct compiler *, stmt_ty);
static int codegen_try_star_except(struct compiler *, stmt_ty);

static int codegen_sync_comprehension_generator(
                                      struct compiler *c, location loc,
                                      asdl_comprehension_seq *generators, int gen_index,
                                      int depth,
                                      expr_ty elt, expr_ty val, int type,
                                      int iter_on_stack);

static int codegen_async_comprehension_generator(
                                      struct compiler *c, location loc,
                                      asdl_comprehension_seq *generators, int gen_index,
                                      int depth,
                                      expr_ty elt, expr_ty val, int type,
                                      int iter_on_stack);

static int codegen_pattern(struct compiler *, pattern_ty, pattern_context *);
static int codegen_match(struct compiler *, stmt_ty);
static int codegen_pattern_subpattern(struct compiler *,
                                      pattern_ty, pattern_context *);
static int codegen_make_closure(struct compiler *c, location loc,
                                PyCodeObject *co, Py_ssize_t flags);

static PyCodeObject *optimize_and_assemble(struct compiler *, int addNone);

/* Add an opcode with an integer argument */
static int
codegen_addop_i(instr_sequence *seq, int opcode, Py_ssize_t oparg, location loc)
{}

#define ADDOP_I

#define ADDOP_I_IN_SCOPE

static int
codegen_addop_noarg(instr_sequence *seq, int opcode, location loc)
{}

#define ADDOP

#define ADDOP_IN_SCOPE

static Py_ssize_t
dict_add_o(PyObject *dict, PyObject *o)
{}

/* 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)
{}

static PyObject*
merge_consts_recursive(PyObject *const_cache, PyObject *o)
{}

static int
codegen_addop_load_const(struct compiler *c, location loc, PyObject *o)
{}

#define ADDOP_LOAD_CONST

#define ADDOP_LOAD_CONST_IN_SCOPE

/* Same as ADDOP_LOAD_CONST, but steals a reference. */
#define ADDOP_LOAD_CONST_NEW

static int
codegen_addop_o(struct compiler *c, location loc,
                int opcode, PyObject *dict, PyObject *o)
{}

#define ADDOP_N

#define ADDOP_N_IN_SCOPE

#define LOAD_METHOD
#define LOAD_SUPER_METHOD
#define LOAD_ZERO_SUPER_ATTR
#define LOAD_ZERO_SUPER_METHOD

static int
codegen_addop_name(struct compiler *c, location loc,
                   int opcode, PyObject *dict, PyObject *o)
{}

#define ADDOP_NAME

static int
codegen_addop_j(instr_sequence *seq, location loc,
                int opcode, jump_target_label target)
{}

#define ADDOP_JUMP

#define ADDOP_COMPARE

#define ADDOP_BINARY

#define ADDOP_INPLACE

#define ADD_YIELD_FROM

#define POP_EXCEPT_AND_RERAISE

#define ADDOP_YIELD

/* VISIT and VISIT_SEQ takes an ASDL type as their second argument.  They use
   the ASDL name to synthesize the name of the C type and the visit function.
*/

#define VISIT

#define VISIT_IN_SCOPE

#define VISIT_SEQ

#define VISIT_SEQ_IN_SCOPE

static int
codegen_call_exit_with_nones(struct compiler *c, location loc)
{}

static int
codegen_add_yield_from(struct compiler *c, location loc, int await)
{}

static int
codegen_pop_except_and_reraise(struct compiler *c, location loc)
{}

/* Unwind a frame block.  If preserve_tos is true, the TOS before
 * popping the blocks will be restored afterwards, unless another
 * return, break or continue is found. In which case, the TOS will
 * be popped.
 */
static int
codegen_unwind_fblock(struct compiler *c, location *ploc,
                      struct fblockinfo *info, int preserve_tos)
{}

/** Unwind block stack. If loop is not NULL, then stop when the first loop is encountered. */
static int
codegen_unwind_fblock_stack(struct compiler *c, location *ploc,
                            int preserve_tos, struct fblockinfo **loop)
{}

static int
codegen_enter_scope(struct compiler *c, identifier name, int scope_type,
                    void *key, int lineno, PyObject *private,
                    _PyCompile_CodeUnitMetadata *umd)
{}

static int
codegen_setup_annotations_scope(struct compiler *c, location loc,
                                void *key, PyObject *name)
{}

static int
codegen_leave_annotations_scope(struct compiler *c, location loc,
                                Py_ssize_t annotations_len)
{}

static int
codegen_process_deferred_annotations(struct compiler *c, location loc)
{}

/* Compile an expression */
static int
codegen_expression(struct compiler *c, expr_ty e)
{}

/* Compile a sequence of statements, checking for a docstring
   and for annotations. */

static int
codegen_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
{}

static location
start_location(asdl_stmt_seq *stmts)
{}

static int
codegen_enter_anonymous_scope(struct compiler* c, mod_ty mod)
{}

static int
codegen_make_closure(struct compiler *c, location loc,
                     PyCodeObject *co, Py_ssize_t flags)
{}

static int
codegen_decorators(struct compiler *c, asdl_expr_seq* decos)
{}

static int
codegen_apply_decorators(struct compiler *c, asdl_expr_seq* decos)
{}

static int
codegen_kwonlydefaults(struct compiler *c, location loc,
                       asdl_arg_seq *kwonlyargs, asdl_expr_seq *kw_defaults)
{}

static int
codegen_visit_annexpr(struct compiler *c, expr_ty annotation)
{}

static int
codegen_argannotation(struct compiler *c, identifier id,
    expr_ty annotation, Py_ssize_t *annotations_len, location loc)
{}

static int
codegen_argannotations(struct compiler *c, asdl_arg_seq* args,
                       Py_ssize_t *annotations_len, location loc)
{}

static int
codegen_annotations_in_scope(struct compiler *c, location loc,
                             arguments_ty args, expr_ty returns,
                             Py_ssize_t *annotations_len)
{}

static int
codegen_annotations(struct compiler *c, location loc,
                    arguments_ty args, expr_ty returns)
{}

static int
codegen_defaults(struct compiler *c, arguments_ty args,
                        location loc)
{}

static Py_ssize_t
codegen_default_arguments(struct compiler *c, location loc,
                          arguments_ty args)
{}

static int
codegen_wrap_in_stopiteration_handler(struct compiler *c)
{}

static int
codegen_type_param_bound_or_default(struct compiler *c, expr_ty e,
                                    identifier name, void *key,
                                    bool allow_starred)
{}

static int
codegen_type_params(struct compiler *c, asdl_type_param_seq *type_params)
{}

static int
codegen_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags,
                      int firstlineno)
{}

static int
codegen_function(struct compiler *c, stmt_ty s, int is_async)
{}

static int
codegen_set_type_params_in_class(struct compiler *c, location loc)
{}


static int
codegen_class_body(struct compiler *c, stmt_ty s, int firstlineno)
{}

static int
codegen_class(struct compiler *c, stmt_ty s)
{}

static int
codegen_typealias_body(struct compiler *c, stmt_ty s)
{}

static int
codegen_typealias(struct compiler *c, stmt_ty s)
{}

/* Return false if the expression is a constant value except named singletons.
   Return true otherwise. */
static bool
check_is_arg(expr_ty e)
{}

static PyTypeObject * infer_type(expr_ty e);

/* Check operands of identity checks ("is" and "is not").
   Emit a warning if any operand is a constant except named singletons.
 */
static int
codegen_check_compare(struct compiler *c, expr_ty e)
{}

static int
codegen_addcompare(struct compiler *c, location loc, cmpop_ty op)
{}

static int
codegen_jump_if(struct compiler *c, location loc,
                expr_ty e, jump_target_label next, int cond)
{}

static int
codegen_ifexp(struct compiler *c, expr_ty e)
{}

static int
codegen_lambda(struct compiler *c, expr_ty e)
{}

static int
codegen_if(struct compiler *c, stmt_ty s)
{}

static int
codegen_for(struct compiler *c, stmt_ty s)
{}


static int
codegen_async_for(struct compiler *c, stmt_ty s)
{}

static int
codegen_while(struct compiler *c, stmt_ty s)
{}

static int
codegen_return(struct compiler *c, stmt_ty s)
{}

static int
codegen_break(struct compiler *c, location loc)
{}

static int
codegen_continue(struct compiler *c, location loc)
{}


/* Code generated for "try: <body> finally: <finalbody>" is as follows:

        SETUP_FINALLY           L
        <code for body>
        POP_BLOCK
        <code for finalbody>
        JUMP E
    L:
        <code for finalbody>
    E:

   The special instructions use the block stack.  Each block
   stack entry contains the instruction that created it (here
   SETUP_FINALLY), the level of the value stack at the time the
   block stack entry was created, and a label (here L).

   SETUP_FINALLY:
    Pushes the current value stack level and the label
    onto the block stack.
   POP_BLOCK:
    Pops en entry from the block stack.

   The block stack is unwound when an exception is raised:
   when a SETUP_FINALLY entry is found, the raised and the caught
   exceptions are pushed onto the value stack (and the exception
   condition is cleared), and the interpreter jumps to the label
   gotten from the block stack.
*/

static int
codegen_try_finally(struct compiler *c, stmt_ty s)
{}

static int
codegen_try_star_finally(struct compiler *c, stmt_ty s)
{}


/*
   Code generated for "try: S except E1 as V1: S1 except E2 as V2: S2 ...":
   (The contents of the value stack is shown in [], with the top
   at the right; 'tb' is trace-back info, 'val' the exception's
   associated value, and 'exc' the exception.)

   Value stack          Label   Instruction     Argument
   []                           SETUP_FINALLY   L1
   []                           <code for S>
   []                           POP_BLOCK
   []                           JUMP            L0

   [exc]                L1:     <evaluate E1>           )
   [exc, E1]                    CHECK_EXC_MATCH         )
   [exc, bool]                  POP_JUMP_IF_FALSE L2    ) only if E1
   [exc]                        <assign to V1>  (or POP if no V1)
   []                           <code for S1>
                                JUMP            L0

   [exc]                L2:     <evaluate E2>
   .............................etc.......................

   [exc]                Ln+1:   RERAISE     # re-raise exception

   []                   L0:     <next statement>

   Of course, parts are not generated if Vi or Ei is not present.
*/
static int
codegen_try_except(struct compiler *c, stmt_ty s)
{}

/*
   Code generated for "try: S except* E1 as V1: S1 except* E2 as V2: S2 ...":
   (The contents of the value stack is shown in [], with the top
   at the right; 'tb' is trace-back info, 'val' the exception instance,
   and 'typ' the exception's type.)

   Value stack                   Label         Instruction     Argument
   []                                         SETUP_FINALLY         L1
   []                                         <code for S>
   []                                         POP_BLOCK
   []                                         JUMP                  L0

   [exc]                            L1:       BUILD_LIST   )  list for raised/reraised excs ("result")
   [orig, res]                                COPY 2       )  make a copy of the original EG

   [orig, res, exc]                           <evaluate E1>
   [orig, res, exc, E1]                       CHECK_EG_MATCH
   [orig, res, rest/exc, match?]              COPY 1
   [orig, res, rest/exc, match?, match?]      POP_JUMP_IF_NONE      C1

   [orig, res, rest, match]                   <assign to V1>  (or POP if no V1)

   [orig, res, rest]                          SETUP_FINALLY         R1
   [orig, res, rest]                          <code for S1>
   [orig, res, rest]                          JUMP                  L2

   [orig, res, rest, i, v]          R1:       LIST_APPEND   3 ) exc raised in except* body - add to res
   [orig, res, rest, i]                       POP
   [orig, res, rest]                          JUMP                  LE2

   [orig, res, rest]                L2:       NOP  ) for lineno
   [orig, res, rest]                          JUMP                  LE2

   [orig, res, rest/exc, None]      C1:       POP

   [orig, res, rest]               LE2:       <evaluate E2>
   .............................etc.......................

   [orig, res, rest]                Ln+1:     LIST_APPEND 1  ) add unhandled exc to res (could be None)

   [orig, res]                                CALL_INTRINSIC_2 PREP_RERAISE_STAR
   [exc]                                      COPY 1
   [exc, exc]                                 POP_JUMP_IF_NOT_NONE  RER
   [exc]                                      POP_TOP
   []                                         JUMP                  L0

   [exc]                            RER:      SWAP 2
   [exc, prev_exc_info]                       POP_EXCEPT
   [exc]                                      RERAISE               0

   []                               L0:       <next statement>
*/
static int
codegen_try_star_except(struct compiler *c, stmt_ty s)
{}

static int
codegen_try(struct compiler *c, stmt_ty s) {}

static int
codegen_try_star(struct compiler *c, stmt_ty s)
{}

static int
codegen_import_as(struct compiler *c, location loc,
                  identifier name, identifier asname)
{}

static int
codegen_import(struct compiler *c, stmt_ty s)
{}

static int
codegen_from_import(struct compiler *c, stmt_ty s)
{}

static int
codegen_assert(struct compiler *c, stmt_ty s)
{}

static int
codegen_stmt_expr(struct compiler *c, location loc, expr_ty value)
{}

static int
codegen_visit_stmt(struct compiler *c, stmt_ty s)
{}

static int
unaryop(unaryop_ty op)
{}

static int
addop_binary(struct compiler *c, location loc, operator_ty binop,
             bool inplace)
{}


static int
codegen_addop_yield(struct compiler *c, location loc) {}

static int
codegen_load_classdict_freevar(struct compiler *c, location loc)
{}

compiler_optype;

static int compiler_resolve_nameop(struct compiler *c, PyObject *mangled, int scope,
                                   compiler_optype *optype, Py_ssize_t *arg);

static int
codegen_nameop(struct compiler *c, location loc,
               identifier name, expr_context_ty ctx)
{}

static int
codegen_boolop(struct compiler *c, expr_ty e)
{}

static int
starunpack_helper(struct compiler *c, location loc,
                  asdl_expr_seq *elts, int pushed,
                  int build, int add, int extend, int tuple)
{}

static int
unpack_helper(struct compiler *c, location loc, asdl_expr_seq *elts)
{}

static int
assignment_helper(struct compiler *c, location loc, asdl_expr_seq *elts)
{}

static int
codegen_list(struct compiler *c, expr_ty e)
{}

static int
codegen_tuple(struct compiler *c, expr_ty e)
{}

static int
codegen_set(struct compiler *c, expr_ty e)
{}

static bool
are_all_items_const(asdl_expr_seq *seq, Py_ssize_t begin, Py_ssize_t end)
{}

static int
codegen_subdict(struct compiler *c, expr_ty e, Py_ssize_t begin, Py_ssize_t end)
{}

static int
codegen_dict(struct compiler *c, expr_ty e)
{}

static int
codegen_compare(struct compiler *c, expr_ty e)
{}

static PyTypeObject *
infer_type(expr_ty e)
{}

static int
check_caller(struct compiler *c, expr_ty e)
{}

static int
check_subscripter(struct compiler *c, expr_ty e)
{}

static int
check_index(struct compiler *c, expr_ty e, expr_ty s)
{}

static int
is_import_originated(struct compiler *c, expr_ty e)
{}

static int
can_optimize_super_call(struct compiler *c, expr_ty attr)
{}

static int
load_args_for_super(struct compiler *c, expr_ty e) {}

// If an attribute access spans multiple lines, update the current start
// location to point to the attribute name.
static location
update_start_location_to_match_attr(struct compiler *c, location loc,
                                    expr_ty attr)
{}

// Return 1 if the method call was optimized, 0 if not, and -1 on error.
static int
maybe_optimize_method_call(struct compiler *c, expr_ty e)
{}

static int
codegen_validate_keywords(struct compiler *c, asdl_keyword_seq *keywords)
{}

static int
codegen_call(struct compiler *c, expr_ty e)
{}

static int
codegen_joined_str(struct compiler *c, expr_ty e)
{}

/* Used to implement f-strings. Format a single value. */
static int
codegen_formatted_value(struct compiler *c, expr_ty e)
{}

static int
codegen_subkwargs(struct compiler *c, location loc,
                  asdl_keyword_seq *keywords,
                  Py_ssize_t begin, Py_ssize_t end)
{}

/* Used by codegen_call_helper and maybe_optimize_method_call to emit
 * a tuple of keyword names before CALL.
 */
static int
codegen_call_simple_kw_helper(struct compiler *c, location loc,
                              asdl_keyword_seq *keywords, Py_ssize_t nkwelts)
{}


/* shared code between codegen_call and codegen_class */
static int
codegen_call_helper(struct compiler *c, location loc,
                    int n, /* Args already pushed */
                    asdl_expr_seq *args,
                    asdl_keyword_seq *keywords)
{}


/* List and set comprehensions and generator expressions work by creating a
  nested function to perform the actual iteration. This means that the
  iteration variables don't leak into the current scope.
  The defined function is called immediately following its definition, with the
  result of that call being the result of the expression.
  The LC/SC version returns the populated container, while the GE version is
  flagged in symtable.c as a generator, so it returns the generator object
  when the function is called.

  Possible cleanups:
    - iterate over the generator sequence instead of using recursion
*/


static int
codegen_comprehension_generator(struct compiler *c, location loc,
                                asdl_comprehension_seq *generators, int gen_index,
                                int depth,
                                expr_ty elt, expr_ty val, int type,
                                int iter_on_stack)
{}

static int
codegen_sync_comprehension_generator(struct compiler *c, location loc,
                                     asdl_comprehension_seq *generators,
                                     int gen_index, int depth,
                                     expr_ty elt, expr_ty val, int type,
                                     int iter_on_stack)
{}

static int
codegen_async_comprehension_generator(struct compiler *c, location loc,
                                      asdl_comprehension_seq *generators,
                                      int gen_index, int depth,
                                      expr_ty elt, expr_ty val, int type,
                                      int iter_on_stack)
{}

inlined_comprehension_state;


static int
codegen_push_inlined_comprehension_locals(struct compiler *c, location loc,
                                          PySTEntryObject *comp,
                                          inlined_comprehension_state *state)
{}

static int compiler_tweak_inlined_comprehension_scopes(struct compiler *c, location loc,
                                                       PySTEntryObject *entry,
                                                       inlined_comprehension_state *state);

static int
push_inlined_comprehension_state(struct compiler *c, location loc,
                                 PySTEntryObject *comp,
                                 inlined_comprehension_state *state)
{}

static int
restore_inlined_comprehension_locals(struct compiler *c, location loc,
                                     inlined_comprehension_state *state)
{}

static int
codegen_pop_inlined_comprehension_locals(struct compiler *c, location loc,
                                         inlined_comprehension_state *state)
{}

static int compiler_revert_inlined_comprehension_scopes(struct compiler *c, location loc,
                                                        inlined_comprehension_state *state);

static int
pop_inlined_comprehension_state(struct compiler *c, location loc,
                                inlined_comprehension_state *state)
{}

static inline int
codegen_comprehension_iter(struct compiler *c, comprehension_ty comp)
{}

static int
codegen_comprehension(struct compiler *c, expr_ty e, int type,
                      identifier name, asdl_comprehension_seq *generators, expr_ty elt,
                      expr_ty val)
{}

static int
codegen_genexp(struct compiler *c, expr_ty e)
{}

static int
codegen_listcomp(struct compiler *c, expr_ty e)
{}

static int
codegen_setcomp(struct compiler *c, expr_ty e)
{}


static int
codegen_dictcomp(struct compiler *c, expr_ty e)
{}


static int
codegen_visit_keyword(struct compiler *c, keyword_ty k)
{}


static int
codegen_with_except_finish(struct compiler *c, jump_target_label cleanup) {}

/*
   Implements the async with statement.

   The semantics outlined in that PEP are as follows:

   async with EXPR as VAR:
       BLOCK

   It is implemented roughly as:

   context = EXPR
   exit = context.__aexit__  # not calling it
   value = await context.__aenter__()
   try:
       VAR = value  # if VAR present in the syntax
       BLOCK
   finally:
       if an exception was raised:
           exc = copy of (exception, instance, traceback)
       else:
           exc = (None, None, None)
       if not (await exit(*exc)):
           raise
 */
static int
codegen_async_with(struct compiler *c, stmt_ty s, int pos)
{}


/*
   Implements the with statement from PEP 343.
   with EXPR as VAR:
       BLOCK
   is implemented as:
        <code for EXPR>
        SETUP_WITH  E
        <code to store to VAR> or POP_TOP
        <code for BLOCK>
        LOAD_CONST (None, None, None)
        CALL_FUNCTION_EX 0
        JUMP  EXIT
    E:  WITH_EXCEPT_START (calls EXPR.__exit__)
        POP_JUMP_IF_TRUE T:
        RERAISE
    T:  POP_TOP (remove exception from stack)
        POP_EXCEPT
        POP_TOP
    EXIT:
 */

static int
codegen_with(struct compiler *c, stmt_ty s, int pos)
{}

static int
codegen_visit_expr(struct compiler *c, expr_ty e)
{}

static bool
is_two_element_slice(expr_ty s)
{}

static int
codegen_augassign(struct compiler *c, stmt_ty s)
{}

static int
codegen_check_ann_expr(struct compiler *c, expr_ty e)
{}

static int
codegen_check_annotation(struct compiler *c, stmt_ty s)
{}

static int
codegen_check_ann_subscr(struct compiler *c, expr_ty e)
{}

static int compiler_add_deferred_annotation(struct compiler *c, stmt_ty s);

static int
codegen_annassign(struct compiler *c, stmt_ty s)
{}

static int
codegen_subscript(struct compiler *c, expr_ty e)
{}

/* Returns the number of the values emitted,
 * thus are needed to build the slice, or -1 if there is an error. */
static int
codegen_slice(struct compiler *c, expr_ty s)
{}


// PEP 634: Structural Pattern Matching

// To keep things simple, all codegen_pattern_* routines follow the convention
// of consuming TOS (the subject for the given pattern) and calling
// jump_to_fail_pop on failure (no match).

// When calling into these routines, it's important that pc->on_top be kept
// updated to reflect the current number of items that we are using on the top
// of the stack: they will be popped on failure, and any name captures will be
// stored *underneath* them on success. This lets us defer all names stores
// until the *entire* pattern matches.

#define WILDCARD_CHECK

#define WILDCARD_STAR_CHECK

// Limit permitted subexpressions, even if the parser & AST validator let them through
#define MATCH_VALUE_EXPR(N)

// Allocate or resize pc->fail_pop to allow for n items to be popped on failure.
static int
ensure_fail_pop(struct compiler *c, pattern_context *pc, Py_ssize_t n)
{}

// Use op to jump to the correct fail_pop block.
static int
jump_to_fail_pop(struct compiler *c, location loc,
                 pattern_context *pc, int op)
{}

// Build all of the fail_pop blocks and reset fail_pop.
static int
emit_and_reset_fail_pop(struct compiler *c, location loc,
                        pattern_context *pc)
{}

static int
codegen_error_duplicate_store(struct compiler *c, location loc, identifier n)
{}

// Duplicate the effect of 3.10's ROT_* instructions using SWAPs.
static int
codegen_pattern_helper_rotate(struct compiler *c, location loc, Py_ssize_t count)
{}

static int
codegen_pattern_helper_store_name(struct compiler *c, location loc,
                                  identifier n, pattern_context *pc)
{}


static int
codegen_pattern_unpack_helper(struct compiler *c, location loc,
                              asdl_pattern_seq *elts)
{}

static int
pattern_helper_sequence_unpack(struct compiler *c, location loc,
                               asdl_pattern_seq *patterns, Py_ssize_t star,
                               pattern_context *pc)
{}

// Like pattern_helper_sequence_unpack, but uses BINARY_SUBSCR instead of
// UNPACK_SEQUENCE / UNPACK_EX. This is more efficient for patterns with a
// starred wildcard like [first, *_] / [first, *_, last] / [*_, last] / etc.
static int
pattern_helper_sequence_subscr(struct compiler *c, location loc,
                               asdl_pattern_seq *patterns, Py_ssize_t star,
                               pattern_context *pc)
{}

// Like codegen_pattern, but turn off checks for irrefutability.
static int
codegen_pattern_subpattern(struct compiler *c,
                            pattern_ty p, pattern_context *pc)
{}

static int
codegen_pattern_as(struct compiler *c, pattern_ty p, pattern_context *pc)
{}

static int
codegen_pattern_star(struct compiler *c, pattern_ty p, pattern_context *pc)
{}

static int
validate_kwd_attrs(struct compiler *c, asdl_identifier_seq *attrs, asdl_pattern_seq* patterns)
{}

static int
codegen_pattern_class(struct compiler *c, pattern_ty p, pattern_context *pc)
{}

static int
codegen_pattern_mapping_key(struct compiler *c, PyObject *seen, pattern_ty p, Py_ssize_t i)
{}

static int
codegen_pattern_mapping(struct compiler *c, pattern_ty p,
                        pattern_context *pc)
{}

static int
codegen_pattern_or(struct compiler *c, pattern_ty p, pattern_context *pc)
{}


static int
codegen_pattern_sequence(struct compiler *c, pattern_ty p,
                         pattern_context *pc)
{}

static int
codegen_pattern_value(struct compiler *c, pattern_ty p, pattern_context *pc)
{}

static int
codegen_pattern_singleton(struct compiler *c, pattern_ty p, pattern_context *pc)
{}

static int
codegen_pattern(struct compiler *c, pattern_ty p, pattern_context *pc)
{}

static int
codegen_match_inner(struct compiler *c, stmt_ty s, pattern_context *pc)
{}

static int
codegen_match(struct compiler *c, stmt_ty s)
{}

#undef WILDCARD_CHECK
#undef WILDCARD_STAR_CHECK


static int
codegen_add_return_at_end(struct compiler *c, int addNone)
{}

#undef ADDOP_I
#undef ADDOP_I_IN_SCOPE
#undef ADDOP
#undef ADDOP_IN_SCOPE
#undef ADDOP_LOAD_CONST
#undef ADDOP_LOAD_CONST_IN_SCOPE
#undef ADDOP_LOAD_CONST_NEW
#undef ADDOP_N
#undef ADDOP_N_IN_SCOPE
#undef ADDOP_NAME
#undef ADDOP_JUMP
#undef ADDOP_COMPARE
#undef ADDOP_BINARY
#undef ADDOP_INPLACE
#undef ADD_YIELD_FROM
#undef POP_EXCEPT_AND_RERAISE
#undef ADDOP_YIELD
#undef VISIT
#undef VISIT_IN_SCOPE
#undef VISIT_SEQ
#undef VISIT_SEQ_IN_SCOPE

/*** end of CODEGEN, start of compiler implementation ***/

/* 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 {};

/* 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
managed by compiler_enter_scope() and compiler_exit_scope().

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.

*/

struct compiler {};


static int
compiler_setup(struct compiler *c, mod_ty mod, PyObject *filename,
               PyCompilerFlags *flags, int optimize, PyArena *arena)
{}

static struct compiler*
new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
             int optimize, PyArena *arena)
{}


PyCodeObject *
_PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
               int optimize, PyArena *arena)
{}

int
_PyCompile_AstOptimize(mod_ty mod, PyObject *filename, PyCompilerFlags *cf,
                       int optimize, PyArena *arena)
{}


static void
compiler_free(struct compiler *c)
{}

static void
compiler_unit_free(struct compiler_unit *u)
{}

#define CAPSULE_NAME

static int
compiler_maybe_add_static_attribute_to_class(struct compiler *c, expr_ty e)
{}

static int
compiler_set_qualname(struct compiler *c)
{}

static Py_ssize_t
compiler_add_const(struct compiler *c, PyObject *o)
{}

static PyObject *
list2dict(PyObject *list)
{}

/* 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)
{}

static int
compiler_enter_scope(struct compiler *c, identifier name, int scope_type,
                     void *key, int lineno, PyObject *private,
                    _PyCompile_CodeUnitMetadata *umd)
{}

static void
compiler_exit_scope(struct compiler *c)
{}

/*
 * Frame block handling functions
 */

static int
compiler_push_fblock(struct compiler *c, location loc,
                     enum fblocktype t, jump_target_label block_label,
                     jump_target_label exit, void *datum)
{}

static void
compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label block_label)
{}

static struct fblockinfo *
compiler_top_fblock(struct compiler *c)
{}

static PyObject *
compiler_deferred_annotations(struct compiler *c)
{}

static int
compiler_codegen(struct compiler *c, mod_ty mod)
{}

static PyCodeObject *
compiler_mod(struct compiler *c, mod_ty mod)
{}

static int
compiler_get_ref_type(struct compiler *c, PyObject *name)
{}

static int
dict_lookup_arg(PyObject *dict, PyObject *name)
{}

static int
compiler_lookup_cellvar(struct compiler *c, PyObject *name)
{}

static int
compiler_lookup_arg(struct compiler *c, PyCodeObject *co, PyObject *name)
{}

static PyObject *
compiler_static_attributes_tuple(struct compiler *c)
{}

static int
compiler_resolve_nameop(struct compiler *c, PyObject *mangled, int scope,
                        compiler_optype *optype, Py_ssize_t *arg)
{}

static int
compiler_tweak_inlined_comprehension_scopes(struct compiler *c, location loc,
                                            PySTEntryObject *entry,
                                            inlined_comprehension_state *state)
{}

static int
compiler_revert_inlined_comprehension_scopes(struct compiler *c, location loc,
                                             inlined_comprehension_state *state)
{}

static int
compiler_add_deferred_annotation(struct compiler *c, stmt_ty s)
{}

/* Raises a SyntaxError and returns ERROR.
 * If something goes wrong, a different exception may be raised.
*/
static int
compiler_error(struct compiler *c, location loc,
               const char *format, ...)
{}

/* Emits a SyntaxWarning and returns 1 on success.
   If a SyntaxWarning raised as error, replaces it with a SyntaxError
   and returns 0.
*/
static int
compiler_warn(struct compiler *c, location loc,
              const char *format, ...)
{}

static PyObject *
compiler_mangle(struct compiler *c, PyObject *name)
{}

static PyObject *
compiler_maybe_mangle(struct compiler *c, PyObject *name)
{}

static instr_sequence *
compiler_instr_sequence(struct compiler *c)
{}

static int
compiler_future_features(struct compiler *c)
{}

static struct symtable *
compiler_symtable(struct compiler *c)
{}

static PySTEntryObject *
compiler_symtable_entry(struct compiler *c)
{}

static int
compiler_optimization_level(struct compiler *c)
{}

static int
compiler_is_interactive(struct compiler *c)
{}

static int
compiler_is_nested_scope(struct compiler *c)
{}

static int
compiler_scope_type(struct compiler *c)
{}

static int
compiler_is_in_inlined_comp(struct compiler *c)
{}

static PyObject *
compiler_qualname(struct compiler *c)
{}

static _PyCompile_CodeUnitMetadata *
compiler_unit_metadata(struct compiler *c)
{}

static PyArena *
compiler_arena(struct compiler *c)
{}

#ifndef NDEBUG
static int
compiler_is_top_level_await(struct compiler *c)
{
    return c->c_flags.cf_flags & PyCF_ALLOW_TOP_LEVEL_AWAIT &&
           c->u->u_ste->ste_type == ModuleBlock;
}
#endif

// Merge *obj* with constant cache, without recursion.
int
_PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj)
{}

static PyObject *
consts_dict_keys_inorder(PyObject *dict)
{}

static PyCodeObject *
optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
                   int code_flags, PyObject *filename)
{}

static int
compute_code_flags(struct compiler *c)
{}


static PyCodeObject *
optimize_and_assemble(struct compiler *c, int addNone)
{}

// 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)
{}

/* Access to compiler optimizations for unit tests.
 *
 * _PyCompile_CodeGen takes an AST, applies code-gen and
 * returns the unoptimized CFG as an instruction list.
 *
 */

PyObject *
_PyCompile_CodeGen(PyObject *ast, PyObject *filename, PyCompilerFlags *pflags,
                   int optimize, int compile_mode)
{}

int _PyCfg_JumpLabelsToTargets(cfg_builder *g);

PyCodeObject *
_PyCompile_Assemble(_PyCompile_CodeUnitMetadata *umd, PyObject *filename,
                    PyObject *seq)
{}


/* Retained for API compatibility.
 * Optimization is now done in _PyCfg_OptimizeCodeUnit */

PyObject *
PyCode_Optimize(PyObject *code, PyObject* Py_UNUSED(consts),
                PyObject *Py_UNUSED(names), PyObject *Py_UNUSED(lnotab_obj))
{}