Skip to content

Commit c17ed50

Browse files
authored
[mypyc] Add experimental C extension librt.vecs (part 2/2) (#20656)
Add support for `vec` types with reference item types, such as `vec[str]` or `vec[MyClass | None]`. Arbitrary union item types aren't supported -- only optional types are accepted. Also add support for nested vecs, such as `vec[vec[i64]]`. No mypyc primitives are included in this PR yet. I'll add them in follow-up PRs. This continues the work started in #20653. Refer to that PR for a more detailed description of the feature. Related issue: mypyc/mypyc#840
1 parent 60d136e commit c17ed50

File tree

12 files changed

+2101
-6
lines changed

12 files changed

+2101
-6
lines changed

mypyc/build.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ class ModDesc(NamedTuple):
114114
"vecs/vec_u8.c",
115115
"vecs/vec_float.c",
116116
"vecs/vec_bool.c",
117+
"vecs/vec_t.c",
118+
"vecs/vec_nested.c",
117119
],
118120
["vecs/librt_vecs.h", "vecs/vec_template.c"],
119121
["vecs"],

mypyc/lib-rt/setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ def run(self) -> None:
142142
"vecs/vec_u8.c",
143143
"vecs/vec_float.c",
144144
"vecs/vec_bool.c",
145+
"vecs/vec_t.c",
146+
"vecs/vec_nested.c",
145147
],
146148
include_dirs=[".", "vecs"],
147149
extra_compile_args=cflags,

mypyc/lib-rt/vecs/librt_vecs.c

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,31 @@ typedef struct {
9696

9797
static PyObject *vec_generic_alias_call(PyObject *self, PyObject *args, PyObject *kw)
9898
{
99-
PyErr_SetString(PyExc_NotImplementedError,
100-
"non-specialized vec construction not yet supported");
101-
return NULL;
99+
static char *kwlist[] = {"", NULL};
100+
PyObject *init = NULL;
101+
if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:vec", kwlist, &init)) {
102+
return NULL;
103+
}
104+
VecGenericAlias *p = (VecGenericAlias *)self;
105+
if (p->depth == 0) {
106+
if (init == NULL) {
107+
VecT vec = VecT_New(0, 0, p->item_type);
108+
if (VEC_IS_ERROR(vec))
109+
return NULL;
110+
return VecT_Box(vec, p->item_type);
111+
} else {
112+
return VecT_FromIterable(p->item_type, init);
113+
}
114+
} else {
115+
if (init == NULL) {
116+
VecNested vec = VecNested_New(0, 0, p->item_type, p->depth);
117+
if (VEC_IS_ERROR(vec))
118+
return NULL;
119+
return VecNested_Box(vec);
120+
} else {
121+
return VecNested_FromIterable(p->item_type, p->depth, init);
122+
}
123+
}
102124
}
103125

104126
static int
@@ -597,6 +619,26 @@ static PyObject *vec_append(PyObject *self, PyObject *args)
597619
if (VEC_IS_ERROR(v))
598620
return NULL;
599621
return VecBool_Box(v);
622+
} else if (VecT_Check(vec)) {
623+
VecT v = ((VecTObject *)vec)->vec;
624+
if (!VecT_ItemCheck(v, item, v.buf->item_type)) {
625+
return NULL;
626+
}
627+
VEC_INCREF(v);
628+
v = VecT_Append(v, item, v.buf->item_type);
629+
if (VEC_IS_ERROR(v))
630+
return NULL;
631+
return VecT_Box(v, v.buf->item_type);
632+
} else if (VecNested_Check(vec)) {
633+
VecNested v = ((VecNestedObject *)vec)->vec;
634+
VecNestedBufItem vecitem;
635+
if (VecNested_UnboxItem(v, item, &vecitem) < 0)
636+
return NULL;
637+
VEC_INCREF(v);
638+
v = VecNested_Append(v, vecitem);
639+
if (VEC_IS_ERROR(v))
640+
return NULL;
641+
return VecNested_Box(v);
600642
} else {
601643
PyErr_Format(PyExc_TypeError, "vec argument expected, got %.100s",
602644
Py_TYPE(vec)->tp_name);
@@ -678,6 +720,26 @@ static PyObject *vec_remove(PyObject *self, PyObject *args)
678720
if (VEC_IS_ERROR(v))
679721
return NULL;
680722
return VecBool_Box(v);
723+
} else if (VecT_Check(vec)) {
724+
VecT v = ((VecTObject *)vec)->vec;
725+
if (!VecT_ItemCheck(v, item, v.buf->item_type)) {
726+
return NULL;
727+
}
728+
VEC_INCREF(v);
729+
v = VecT_Remove(v, item);
730+
if (VEC_IS_ERROR(v))
731+
return NULL;
732+
return VecT_Box(v, v.buf->item_type);
733+
} else if (VecNested_Check(vec)) {
734+
VecNested v = ((VecNestedObject *)vec)->vec;
735+
VecNestedBufItem vecitem;
736+
if (VecNested_UnboxItem(v, item, &vecitem) < 0)
737+
return NULL;
738+
VEC_INCREF(v);
739+
v = VecNested_Remove(v, vecitem);
740+
if (VEC_IS_ERROR(v))
741+
return NULL;
742+
return VecNested_Box(v);
681743
} else {
682744
PyErr_Format(PyExc_TypeError, "vec argument expected, got %.100s",
683745
Py_TYPE(vec)->tp_name);
@@ -756,6 +818,38 @@ static PyObject *vec_pop(PyObject *self, PyObject *args)
756818
if ((result_item0 = VecBool_Box(r.f0)) == NULL)
757819
return NULL;
758820
result_item1 = VecBool_BoxItem(r.f1);
821+
} else if (VecT_Check(vec)) {
822+
VecT v = ((VecTObject *)vec)->vec;
823+
VEC_INCREF(v);
824+
VecTPopResult r;
825+
r = VecT_Pop(v, index);
826+
if (VEC_IS_ERROR(r.f0))
827+
return NULL;
828+
result_item0 = VecT_Box(r.f0, v.buf->item_type);
829+
if (result_item0 == NULL) {
830+
Py_DECREF(r.f1);
831+
return NULL;
832+
}
833+
result_item1 = r.f1;
834+
} else if (VecNested_Check(vec)) {
835+
VecNested v = ((VecNestedObject *)vec)->vec;
836+
VEC_INCREF(v);
837+
VecNestedPopResult r;
838+
r = VecNested_Pop(v, index);
839+
if (VEC_IS_ERROR(r.f0))
840+
return NULL;
841+
result_item0 = VecNested_Box(r.f0);
842+
if (result_item0 == NULL) {
843+
Py_DECREF(r.f0.buf);
844+
Py_DECREF(r.f1.buf);
845+
return NULL;
846+
}
847+
result_item1 = VecNested_BoxItem(r.f0, r.f1);
848+
if (result_item1 == NULL) {
849+
Py_DECREF(result_item0);
850+
Py_DECREF(r.f1.buf);
851+
return NULL;
852+
}
759853
} else {
760854
PyErr_Format(PyExc_TypeError, "vec argument expected, got %.100s",
761855
Py_TYPE(vec)->tp_name);
@@ -780,6 +874,8 @@ static PyObject *vec_pop(PyObject *self, PyObject *args)
780874
}
781875

782876
static VecCapsule Capsule = {
877+
&Vec_TAPI,
878+
&Vec_NestedAPI,
783879
&Vec_I64API,
784880
&Vec_I32API,
785881
&Vec_I16API,
@@ -846,6 +942,16 @@ librt_vecs_module_exec(PyObject *m)
846942
if (PyType_Ready(&VecGenericAliasType) < 0)
847943
return -1;
848944

945+
if (PyType_Ready(&VecTType) < 0)
946+
return -1;
947+
if (PyType_Ready(&VecTBufType) < 0)
948+
return -1;
949+
950+
if (PyType_Ready(&VecNestedType) < 0)
951+
return -1;
952+
if (PyType_Ready(&VecNestedBufType) < 0)
953+
return -1;
954+
849955
if (PyType_Ready(&VecI64Type) < 0)
850956
return -1;
851957
if (PyType_Ready(&VecI64BufType) < 0)

0 commit comments

Comments
 (0)