Skip to content

gh-121404: pass metadata to compiler_enter_scope (optionally) so that codegen functions don't need to set it on the code unit #123078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 82 additions & 58 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,7 +1057,8 @@ codegen_addop_j(instr_sequence *seq, location loc,

static int
compiler_enter_scope(struct compiler *c, identifier name, int scope_type,
void *key, int lineno, PyObject *private)
void *key, int lineno, PyObject *private,
_PyCompile_CodeUnitMetadata *umd)
{
location loc = LOCATION(lineno, lineno, 0, 0);

Expand All @@ -1069,9 +1070,14 @@ compiler_enter_scope(struct compiler *c, identifier name, int scope_type,
return ERROR;
}
u->u_scope_type = scope_type;
u->u_metadata.u_argcount = 0;
u->u_metadata.u_posonlyargcount = 0;
u->u_metadata.u_kwonlyargcount = 0;
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);
Expand Down Expand Up @@ -1441,14 +1447,19 @@ compiler_unwind_fblock_stack(struct compiler *c, location *ploc,
}

static int
compiler_setup_annotations_scope(struct compiler *c, location loc,
void *key, PyObject *name)
codegen_setup_annotations_scope(struct compiler *c, location loc,
void *key, PyObject *name)
{
if (compiler_enter_scope(c, name, COMPILER_SCOPE_ANNOTATIONS,
key, loc.lineno, NULL) == -1) {
return ERROR;
}
c->u->u_metadata.u_posonlyargcount = 1;
_PyCompile_CodeUnitMetadata umd = {
.u_posonlyargcount = 1,
};
RETURN_IF_ERROR(
compiler_enter_scope(c, name, COMPILER_SCOPE_ANNOTATIONS,
key, loc.lineno, NULL, &umd));
assert(c->u->u_metadata.u_posonlyargcount == 1);
assert(c->u->u_metadata.u_argcount == 0);
assert(c->u->u_metadata.u_kwonlyargcount == 0);

// if .format != 1: raise NotImplementedError
_Py_DECLARE_STR(format, ".format");
ADDOP_I(c, loc, LOAD_FAST, 0);
Expand All @@ -1463,8 +1474,8 @@ compiler_setup_annotations_scope(struct compiler *c, location loc,
}

static int
compiler_leave_annotations_scope(struct compiler *c, location loc,
Py_ssize_t annotations_len)
codegen_leave_annotations_scope(struct compiler *c, location loc,
Py_ssize_t annotations_len)
{
ADDOP_I(c, loc, BUILD_MAP, annotations_len);
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
Expand Down Expand Up @@ -1534,8 +1545,8 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
assert(ste->ste_annotation_block != NULL);
PyObject *deferred_anno = Py_NewRef(c->u->u_deferred_annotations);
void *key = (void *)((uintptr_t)ste->ste_id + 1);
if (compiler_setup_annotations_scope(c, loc, key,
ste->ste_annotation_block->ste_name) == -1) {
if (codegen_setup_annotations_scope(c, loc, key,
ste->ste_annotation_block->ste_name) == -1) {
Py_DECREF(deferred_anno);
return ERROR;
}
Expand All @@ -1555,7 +1566,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
Py_DECREF(deferred_anno);

RETURN_IF_ERROR(
compiler_leave_annotations_scope(c, loc, annotations_len)
codegen_leave_annotations_scope(c, loc, annotations_len)
);
RETURN_IF_ERROR(
compiler_nameop(c, loc, &_Py_ID(__annotate__), Store)
Expand Down Expand Up @@ -1618,7 +1629,7 @@ compiler_enter_anonymous_scope(struct compiler* c, mod_ty mod)
_Py_DECLARE_STR(anon_module, "<module>");
RETURN_IF_ERROR(
compiler_enter_scope(c, &_Py_STR(anon_module), COMPILER_SCOPE_MODULE,
mod, 1, NULL));
mod, 1, NULL, NULL));
return SUCCESS;
}

Expand Down Expand Up @@ -1828,7 +1839,7 @@ compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
}

static int
compiler_argannotation(struct compiler *c, identifier id,
codegen_argannotation(struct compiler *c, identifier id,
expr_ty annotation, Py_ssize_t *annotations_len, location loc)
{
if (!annotation) {
Expand Down Expand Up @@ -1862,14 +1873,14 @@ compiler_argannotation(struct compiler *c, identifier id,
}

static int
compiler_argannotations(struct compiler *c, asdl_arg_seq* args,
Py_ssize_t *annotations_len, location loc)
codegen_argannotations(struct compiler *c, asdl_arg_seq* args,
Py_ssize_t *annotations_len, location loc)
{
int i;
for (i = 0; i < asdl_seq_LEN(args); i++) {
arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
RETURN_IF_ERROR(
compiler_argannotation(
codegen_argannotation(
c,
arg->arg,
arg->annotation,
Expand All @@ -1880,40 +1891,40 @@ compiler_argannotations(struct compiler *c, asdl_arg_seq* args,
}

static int
compiler_annotations_in_scope(struct compiler *c, location loc,
arguments_ty args, expr_ty returns,
Py_ssize_t *annotations_len)
codegen_annotations_in_scope(struct compiler *c, location loc,
arguments_ty args, expr_ty returns,
Py_ssize_t *annotations_len)
{
RETURN_IF_ERROR(
compiler_argannotations(c, args->args, annotations_len, loc));
codegen_argannotations(c, args->args, annotations_len, loc));

RETURN_IF_ERROR(
compiler_argannotations(c, args->posonlyargs, annotations_len, loc));
codegen_argannotations(c, args->posonlyargs, annotations_len, loc));

if (args->vararg && args->vararg->annotation) {
RETURN_IF_ERROR(
compiler_argannotation(c, args->vararg->arg,
args->vararg->annotation, annotations_len, loc));
codegen_argannotation(c, args->vararg->arg,
args->vararg->annotation, annotations_len, loc));
}

RETURN_IF_ERROR(
compiler_argannotations(c, args->kwonlyargs, annotations_len, loc));
codegen_argannotations(c, args->kwonlyargs, annotations_len, loc));

if (args->kwarg && args->kwarg->annotation) {
RETURN_IF_ERROR(
compiler_argannotation(c, args->kwarg->arg,
args->kwarg->annotation, annotations_len, loc));
codegen_argannotation(c, args->kwarg->arg,
args->kwarg->annotation, annotations_len, loc));
}

RETURN_IF_ERROR(
compiler_argannotation(c, &_Py_ID(return), returns, annotations_len, loc));
codegen_argannotation(c, &_Py_ID(return), returns, annotations_len, loc));

return 0;
}

static int
compiler_annotations(struct compiler *c, location loc,
arguments_ty args, expr_ty returns)
codegen_annotations(struct compiler *c, location loc,
arguments_ty args, expr_ty returns)
{
/* Push arg annotation names and values.
The expressions are evaluated separately from the rest of the source code.
Expand All @@ -1930,15 +1941,15 @@ compiler_annotations(struct compiler *c, location loc,
bool annotations_used = ste->ste_annotations_used;

if (annotations_used) {
if (compiler_setup_annotations_scope(c, loc, (void *)args,
ste->ste_name) < 0) {
if (codegen_setup_annotations_scope(c, loc, (void *)args,
ste->ste_name) < 0) {
Py_DECREF(ste);
return ERROR;
}
}
Py_DECREF(ste);

if (compiler_annotations_in_scope(c, loc, args, returns, &annotations_len) < 0) {
if (codegen_annotations_in_scope(c, loc, args, returns, &annotations_len) < 0) {
if (annotations_used) {
compiler_exit_scope(c);
}
Expand All @@ -1947,7 +1958,7 @@ compiler_annotations(struct compiler *c, location loc,

if (annotations_used) {
RETURN_IF_ERROR(
compiler_leave_annotations_scope(c, loc, annotations_len)
codegen_leave_annotations_scope(c, loc, annotations_len)
);
return MAKE_FUNCTION_ANNOTATE;
}
Expand Down Expand Up @@ -2011,7 +2022,7 @@ compiler_type_param_bound_or_default(struct compiler *c, expr_ty e,
{
PyObject *defaults = PyTuple_Pack(1, _PyLong_GetOne());
ADDOP_LOAD_CONST_NEW(c, LOC(e), defaults);
if (compiler_setup_annotations_scope(c, LOC(e), key, name) == -1) {
if (codegen_setup_annotations_scope(c, LOC(e), key, name) == -1) {
return ERROR;
}
if (allow_starred && e->kind == Starred_kind) {
Expand Down Expand Up @@ -2155,8 +2166,13 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
scope_type = COMPILER_SCOPE_FUNCTION;
}

_PyCompile_CodeUnitMetadata umd = {
.u_argcount = asdl_seq_LEN(args->args),
.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs),
.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs),
};
RETURN_IF_ERROR(
compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno, NULL));
compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno, NULL, &umd));

Py_ssize_t first_instr = 0;
PyObject *docstring = _PyAST_GetDocString(body);
Expand All @@ -2181,9 +2197,9 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
}
Py_CLEAR(docstring);

c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
assert(c->u->u_metadata.u_argcount == asdl_seq_LEN(args->args));
assert(c->u->u_metadata.u_posonlyargcount == asdl_seq_LEN(args->posonlyargs));
assert(c->u->u_metadata.u_kwonlyargcount == asdl_seq_LEN(args->kwonlyargs));

NEW_JUMP_TARGET_LABEL(c, start);
USE_LABEL(c, start);
Expand Down Expand Up @@ -2222,7 +2238,7 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
}

static int
compiler_function(struct compiler *c, stmt_ty s, int is_async)
codegen_function(struct compiler *c, stmt_ty s, int is_async)
{
arguments_ty args;
expr_ty returns;
Expand Down Expand Up @@ -2282,8 +2298,11 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
if (!type_params_name) {
return ERROR;
}
_PyCompile_CodeUnitMetadata umd = {
.u_argcount = num_typeparam_args,
};
if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_ANNOTATIONS,
(void *)type_params, firstlineno, NULL) == -1) {
(void *)type_params, firstlineno, NULL, &umd) == -1) {
Py_DECREF(type_params_name);
return ERROR;
}
Expand All @@ -2294,7 +2313,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
}
}

int annotations_flag = compiler_annotations(c, loc, args, returns);
int annotations_flag = codegen_annotations(c, loc, args, returns);
if (annotations_flag < 0) {
if (is_generic) {
compiler_exit_scope(c);
Expand All @@ -2314,7 +2333,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
ADDOP_I_IN_SCOPE(c, loc, SWAP, 2);
ADDOP_I_IN_SCOPE(c, loc, CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS);

c->u->u_metadata.u_argcount = num_typeparam_args;
assert(c->u->u_metadata.u_argcount == num_typeparam_args);
PyCodeObject *co = optimize_and_assemble(c, 0);
compiler_exit_scope(c);
if (co == NULL) {
Expand Down Expand Up @@ -2365,7 +2384,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
/* 1. compile the class body into a code object */
RETURN_IF_ERROR(
compiler_enter_scope(c, s->v.ClassDef.name, COMPILER_SCOPE_CLASS,
(void *)s, firstlineno, s->v.ClassDef.name));
(void *)s, firstlineno, s->v.ClassDef.name, NULL));

location loc = LOCATION(firstlineno, firstlineno, 0, 0);
/* load (global) __name__ ... */
Expand Down Expand Up @@ -2508,7 +2527,7 @@ compiler_class(struct compiler *c, stmt_ty s)
return ERROR;
}
if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_ANNOTATIONS,
(void *)type_params, firstlineno, s->v.ClassDef.name) == -1) {
(void *)type_params, firstlineno, s->v.ClassDef.name, NULL) == -1) {
Py_DECREF(type_params_name);
return ERROR;
}
Expand Down Expand Up @@ -2592,7 +2611,7 @@ compiler_typealias_body(struct compiler *c, stmt_ty s)
PyObject *defaults = PyTuple_Pack(1, _PyLong_GetOne());
ADDOP_LOAD_CONST_NEW(c, loc, defaults);
RETURN_IF_ERROR(
compiler_setup_annotations_scope(c, LOC(s), s, name));
codegen_setup_annotations_scope(c, LOC(s), s, name));
/* Make None the first constant, so the evaluate function can't have a
docstring. */
RETURN_IF_ERROR(compiler_add_const(c, Py_None));
Expand Down Expand Up @@ -2627,7 +2646,7 @@ compiler_typealias(struct compiler *c, stmt_ty s)
return ERROR;
}
if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_ANNOTATIONS,
(void *)type_params, loc.lineno, NULL) == -1) {
(void *)type_params, loc.lineno, NULL, NULL) == -1) {
Py_DECREF(type_params_name);
return ERROR;
}
Expand Down Expand Up @@ -2889,18 +2908,23 @@ compiler_lambda(struct compiler *c, expr_ty e)
return ERROR;
}

_PyCompile_CodeUnitMetadata umd = {
.u_argcount = asdl_seq_LEN(args->args),
.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs),
.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs),
};
_Py_DECLARE_STR(anon_lambda, "<lambda>");
RETURN_IF_ERROR(
compiler_enter_scope(c, &_Py_STR(anon_lambda), COMPILER_SCOPE_LAMBDA,
(void *)e, e->lineno, NULL));
(void *)e, e->lineno, NULL, &umd));

/* Make None the first constant, so the lambda can't have a
docstring. */
RETURN_IF_ERROR(compiler_add_const(c, Py_None));

c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
assert(c->u->u_metadata.u_argcount == asdl_seq_LEN(args->args));
assert(c->u->u_metadata.u_posonlyargcount == asdl_seq_LEN(args->posonlyargs));
assert(c->u->u_metadata.u_kwonlyargcount == asdl_seq_LEN(args->kwonlyargs));
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
if (SYMTABLE_ENTRY(c)->ste_generator) {
co = optimize_and_assemble(c, 0);
Expand Down Expand Up @@ -3867,7 +3891,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)

switch (s->kind) {
case FunctionDef_kind:
return compiler_function(c, s, 0);
return codegen_function(c, s, 0);
case ClassDef_kind:
return compiler_class(c, s);
case TypeAlias_kind:
Expand Down Expand Up @@ -3949,7 +3973,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
case With_kind:
return compiler_with(c, s, 0);
case AsyncFunctionDef_kind:
return compiler_function(c, s, 1);
return codegen_function(c, s, 1);
case AsyncWith_kind:
return compiler_async_with(c, s, 0);
case AsyncFor_kind:
Expand Down Expand Up @@ -5674,7 +5698,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
}
else {
if (compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION,
(void *)e, e->lineno, NULL) < 0) {
(void *)e, e->lineno, NULL, NULL) < 0) {
goto error;
}
}
Expand Down
Loading