Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 47d24d9

Browse files
committed
Add support for type aliases (but not for computing the value)
1 parent 2b844f4 commit 47d24d9

7 files changed

Lines changed: 232 additions & 3 deletions

File tree

Include/internal/pycore_intrinsics.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
#define INTRINSIC_PARAMSPEC 8
1212
#define INTRINSIC_TYPEVARTUPLE 9
1313
#define INTRINSIC_SUBSCRIPT_GENERIC 10
14+
#define INTRINSIC_TYPEALIAS 11
1415

15-
#define MAX_INTRINSIC_1 10
16+
#define MAX_INTRINSIC_1 11
1617

1718

1819
/* Binary Functions: */

Include/internal/pycore_typevarobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ extern PyTypeObject _PyTypeVarTuple_Type;
1313
extern PyTypeObject _PyParamSpec_Type;
1414
extern PyTypeObject _PyParamSpecArgs_Type;
1515
extern PyTypeObject _PyParamSpecKwargs_Type;
16+
extern PyTypeObject _PyTypeAlias_Type;
1617

1718
extern PyObject *_Py_make_typevar(const char *, PyObject *);
1819
extern PyObject *_Py_make_paramspec(const char *);
1920
extern PyObject *_Py_make_typevartuple(const char *);
21+
extern PyObject *_Py_make_typealias(PyThreadState* unused, PyObject *);
2022
extern PyObject *_Py_subscript_generic(PyObject *);
2123
extern int _Py_initialize_generic(PyInterpreterState *);
2224

Objects/clinic/typevarobject.c.h

Lines changed: 18 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Objects/typevarobject.c

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ class paramspec "paramspecobject *" "&_PyParamSpec_Type"
1111
class paramspecargs "paramspecargsobject *" "&_PyParamSpecArgs_Type"
1212
class paramspeckwargs "paramspeckwargsobject *" "&_PyParamSpecKwargs_Type"
1313
class typevartuple "typevartupleobject *" "&_PyTypeVarTuple_Type"
14+
class typealias "typealiasobject *" "&_PyTypeAlias_Type"
1415
class Generic "PyObject *" "&PyGeneric_Type"
1516
[clinic start generated code]*/
16-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b0f1a94d4a27c0c]*/
17+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=a775b1d0f0b88d23]*/
1718

1819
typedef struct {
1920
PyObject_HEAD
@@ -39,6 +40,14 @@ typedef struct {
3940
bool autovariance;
4041
} paramspecobject;
4142

43+
typedef struct {
44+
PyObject_HEAD
45+
const char *name;
46+
PyObject *type_params;
47+
PyObject *compute_value;
48+
PyObject *value;
49+
} typealiasobject;
50+
4251
#include "clinic/typevarobject.c.h"
4352

4453
static PyObject *call_typing_func_object(const char *name, PyObject *args) {
@@ -1030,6 +1039,111 @@ PyObject *_Py_make_typevartuple(const char *name) {
10301039
return (PyObject *)typevartupleobject_alloc(name);
10311040
}
10321041

1042+
static void
1043+
typealias_dealloc(PyObject *self)
1044+
{
1045+
typealiasobject *ta = (typealiasobject *)self;
1046+
free((void *)ta->name);
1047+
Py_XDECREF(ta->type_params);
1048+
Py_XDECREF(ta->compute_value);
1049+
Py_XDECREF(ta->value);
1050+
Py_TYPE(self)->tp_free(self);
1051+
}
1052+
1053+
static PyObject *
1054+
typealias_repr(PyObject *self)
1055+
{
1056+
typealiasobject *ta = (typealiasobject *)self;
1057+
return PyUnicode_FromFormat("%s", ta->name);
1058+
}
1059+
1060+
static PyMemberDef typealias_members[] = {
1061+
{"__name__", T_STRING, offsetof(typealiasobject, name), READONLY},
1062+
{"__type_params__", T_OBJECT, offsetof(typealiasobject, type_params), READONLY},
1063+
{0}
1064+
};
1065+
1066+
static typealiasobject *
1067+
typealias_alloc(const char *name, PyObject *type_params, PyObject *compute_value)
1068+
{
1069+
typealiasobject *ta = PyObject_GC_New(typealiasobject, &_PyTypeAlias_Type);
1070+
if (ta == NULL) {
1071+
return NULL;
1072+
}
1073+
ta->name = strdup(name);
1074+
if (ta->name == NULL) {
1075+
Py_DECREF(ta);
1076+
return NULL;
1077+
}
1078+
ta->type_params = Py_XNewRef(type_params);
1079+
ta->compute_value = Py_NewRef(compute_value);
1080+
ta->value = NULL;
1081+
PyObject_GC_Track(ta);
1082+
return ta;
1083+
}
1084+
1085+
static int typealias_traverse(typealiasobject *self, visitproc visit, void *arg)
1086+
{
1087+
Py_VISIT(self->type_params);
1088+
Py_VISIT(self->compute_value);
1089+
Py_VISIT(self->value);
1090+
return 0;
1091+
}
1092+
1093+
/*[clinic input]
1094+
typealias.__reduce__ as typealias_reduce
1095+
1096+
[clinic start generated code]*/
1097+
1098+
static PyObject *
1099+
typealias_reduce_impl(typealiasobject *self)
1100+
/*[clinic end generated code: output=913724f92ad3b39b input=4f06fbd9472ec0f1]*/
1101+
{
1102+
return PyUnicode_FromString(self->name);
1103+
}
1104+
1105+
static PyMethodDef typealias_methods[] = {
1106+
TYPEALIAS_REDUCE_METHODDEF
1107+
{0}
1108+
};
1109+
1110+
PyDoc_STRVAR(typealias_doc,
1111+
"Type alias.\n\
1112+
\n\
1113+
Type aliases are created through the type statement:\n\
1114+
\n\
1115+
type Alias = int\n\
1116+
");
1117+
1118+
PyTypeObject _PyTypeAlias_Type = {
1119+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
1120+
.tp_name = "TypeAlias",
1121+
.tp_basicsize = sizeof(typealiasobject),
1122+
.tp_dealloc = typealias_dealloc,
1123+
.tp_repr = typealias_repr,
1124+
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE,
1125+
.tp_members = typealias_members,
1126+
.tp_methods = typealias_methods,
1127+
.tp_doc = typealias_doc,
1128+
.tp_traverse = typealias_traverse,
1129+
};
1130+
1131+
PyObject *
1132+
_Py_make_typealias(PyThreadState* unused, PyObject *args)
1133+
{
1134+
assert(PyTuple_Check(args));
1135+
assert(PyTuple_GET_SIZE(args) == 3);
1136+
PyObject *name = PyTuple_GET_ITEM(args, 0);
1137+
assert(PyUnicode_Check(name));
1138+
const char *name_str = PyUnicode_AsUTF8(name);
1139+
if (name_str == NULL) {
1140+
return NULL;
1141+
}
1142+
PyObject *type_params = PyTuple_GET_ITEM(args, 1);
1143+
PyObject *compute_value = PyTuple_GET_ITEM(args, 2);
1144+
return (PyObject *)typealias_alloc(name_str, type_params, compute_value);
1145+
}
1146+
10331147
PyDoc_STRVAR(generic_doc,
10341148
"Abstract base class for generic types.\n\
10351149
\n\

Python/compile.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2522,6 +2522,73 @@ compiler_class(struct compiler *c, stmt_ty s)
25222522
return SUCCESS;
25232523
}
25242524

2525+
static int
2526+
compiler_typealias(struct compiler *c, stmt_ty s)
2527+
{
2528+
location loc = LOC(s);
2529+
asdl_typeparam_seq *typeparams = s->v.TypeAlias.typeparams;
2530+
PyObject *name = s->v.TypeAlias.name->v.Name.id;
2531+
if (typeparams) {
2532+
ADDOP(c, loc, PUSH_NULL);
2533+
PyObject *typeparams_name = PyUnicode_FromFormat("<generic parameters of %U>",
2534+
name);
2535+
if (!typeparams_name) {
2536+
return ERROR;
2537+
}
2538+
if (compiler_enter_scope(c, typeparams_name, COMPILER_SCOPE_TYPEPARAMS,
2539+
(void *)typeparams, loc.lineno) == -1) {
2540+
Py_DECREF(typeparams_name);
2541+
return ERROR;
2542+
}
2543+
Py_DECREF(typeparams_name);
2544+
ADDOP_LOAD_CONST(c, loc, name);
2545+
RETURN_IF_ERROR(compiler_type_params(c, typeparams));
2546+
}
2547+
else {
2548+
ADDOP_LOAD_CONST(c, loc, name);
2549+
ADDOP_LOAD_CONST(c, loc, Py_None);
2550+
}
2551+
RETURN_IF_ERROR(
2552+
compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, s, loc.lineno));
2553+
/* Make None the first constant, so the evaluate function can't have a
2554+
docstring. */
2555+
RETURN_IF_ERROR(compiler_add_const(c->c_const_cache, c->u, Py_None));
2556+
VISIT_IN_SCOPE(c, expr, s->v.TypeAlias.value);
2557+
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
2558+
PyCodeObject *co = assemble(c, 1);
2559+
compiler_exit_scope(c);
2560+
if (co == NULL) {
2561+
return ERROR;
2562+
}
2563+
if (compiler_make_closure(c, loc, co, 0) < 0) {
2564+
Py_DECREF(co);
2565+
return ERROR;
2566+
}
2567+
Py_DECREF(co);
2568+
ADDOP_I(c, loc, BUILD_TUPLE, 3);
2569+
ADDOP_I(c, loc, CALL_INTRINSIC_1, INTRINSIC_TYPEALIAS);
2570+
if (typeparams) {
2571+
int is_in_class = c->u->u_ste->ste_type_params_in_class;
2572+
c->u->u_argcount = is_in_class;
2573+
PyCodeObject *co = assemble(c, 0);
2574+
compiler_exit_scope(c);
2575+
if (co == NULL) {
2576+
return ERROR;
2577+
}
2578+
if (compiler_make_closure(c, loc, co, 0) < 0) {
2579+
Py_DECREF(co);
2580+
return ERROR;
2581+
}
2582+
Py_DECREF(co);
2583+
if (is_in_class) {
2584+
ADDOP(c, loc, LOAD_LOCALS);
2585+
}
2586+
ADDOP_I(c, loc, CALL, is_in_class);
2587+
}
2588+
RETURN_IF_ERROR(compiler_nameop(c, loc, name, Store));
2589+
return SUCCESS;
2590+
}
2591+
25252592
/* Return false if the expression is a constant value except named singletons.
25262593
Return true otherwise. */
25272594
static bool
@@ -3732,6 +3799,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
37323799
return compiler_function(c, s, 0);
37333800
case ClassDef_kind:
37343801
return compiler_class(c, s);
3802+
case TypeAlias_kind:
3803+
return compiler_typealias(c, s);
37353804
case Return_kind:
37363805
return compiler_return(c, s);
37373806
case Delete_kind:

Python/intrinsics.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ _PyIntrinsics_UnaryFunctions[] = {
240240
[INTRINSIC_PARAMSPEC] = make_paramspec,
241241
[INTRINSIC_TYPEVARTUPLE] = make_typevartuple,
242242
[INTRINSIC_SUBSCRIPT_GENERIC] = subscript_generic,
243+
[INTRINSIC_TYPEALIAS] = _Py_make_typealias,
243244
};
244245

245246

Python/symtable.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,31 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
13491349
}
13501350
break;
13511351
}
1352+
case TypeAlias_kind:
1353+
VISIT(st, expr, s->v.TypeAlias.name);
1354+
assert(s->v.TypeAlias.name->kind == Name_kind);
1355+
PyObject *name = s->v.TypeAlias.name->v.Name.id;
1356+
if (s->v.TypeAlias.typeparams) {
1357+
if (!symtable_enter_typeparam_block(
1358+
st, name,
1359+
(void *)s->v.TypeAlias.typeparams,
1360+
false, false, false,
1361+
LOCATION(s))) {
1362+
VISIT_QUIT(st, 0);
1363+
}
1364+
VISIT_SEQ(st, typeparam, s->v.TypeAlias.typeparams);
1365+
}
1366+
if (!symtable_enter_block(st, name, FunctionBlock,
1367+
(void *)s, LOCATION(s)))
1368+
VISIT_QUIT(st, 0);
1369+
VISIT(st, expr, s->v.TypeAlias.value);
1370+
if (!symtable_exit_block(st))
1371+
VISIT_QUIT(st, 0);
1372+
if (s->v.TypeAlias.typeparams) {
1373+
if (!symtable_exit_block(st))
1374+
VISIT_QUIT(st, 0);
1375+
}
1376+
break;
13521377
case Return_kind:
13531378
if (s->v.Return.value) {
13541379
VISIT(st, expr, s->v.Return.value);

0 commit comments

Comments
 (0)