29 : fPyClass(nullptr), fNonTemplated(nullptr), fTemplated(nullptr),
30 fLowPriority(nullptr), fDoc(nullptr) {
44 for (
const auto&
c :
p.second) {
53 bool isGreedy =
false;
73 fTI->fTemplated->AdoptMethod(pc);
81 std::string proto =
"";
82 std::string protoPair =
"";
96 PyObject* tpArgs = PyTuple_New(argc);
97 for (Py_ssize_t i = 0; i < argc; ++i) {
100 bool bArgSet =
false;
105 PyObject*
f = PyUnicode_FromFormat(
"%s%s", tn->
fTI->fCppName.c_str(),
107 PyTuple_SET_ITEM(tpArgs, i,
f);
113 memset(&bufinfo, 0,
sizeof(Py_buffer));
115 if (PyObject_GetBuffer(itemi, &bufinfo, PyBUF_FORMAT) == 0) {
116 for (
int j = 0; j < bufinfo.ndim; ++j)
118 PyBuffer_Release(&bufinfo);
126 PyTuple_SET_ITEM(tpArgs, i, pyptrname);
139 if (!bArgSet && pytc) {
154 PyTuple_SET_ITEM(tpArgs, i, pyactname);
166 PyTuple_SET_ITEM(tpArgs, i, tp);
170 PyObject* pyargs = PyTuple_New(argc);
171 for (Py_ssize_t i = 0; i < argc; ++i) {
174 PyTuple_SET_ITEM(pyargs, i, item);
176 const std::string& name_v1 =
183 if (!PyErr_Occurred()) {
184 bool has2Tuple =
false;
185 for (Py_ssize_t i = 0; i < argc; ++i) {
187 if (PyTuple_CheckExact(itemi) && PyTuple_GET_SIZE(itemi) == 2) {
194 PyObject* tpArgsPair = PyTuple_New(argc);
195 for (Py_ssize_t i = 0; i < argc; ++i) {
198 if (PyTuple_CheckExact(itemi) && PyTuple_GET_SIZE(itemi) == 2) {
199 PyObject* subtypes = PyTuple_New(2);
200 for (Py_ssize_t j = 0; j < 2; ++j) {
203 PyTuple_SET_ITEM(subtypes, j, tp);
206 nullptr, subtypes, itemi, pref, 0,
nullptr);
208 if (!PyErr_Occurred() && 2 < sub.size())
209 entry = PyUnicode_FromString((
"std::pair" + sub).c_str());
214 entry = PyTuple_GET_ITEM(tpArgs, i);
217 PyTuple_SET_ITEM(tpArgsPair, i, entry);
221 nullptr, tpArgsPair, pyargs, pref, 0,
nullptr);
222 Py_DECREF(tpArgsPair);
223 if (!PyErr_Occurred() && name_v2.size())
224 protoPair = name_v2.substr(1, name_v2.size() - 2);
235 if (PyErr_Occurred()) {
240 proto = name_v1.substr(1, name_v1.size() - 2);
247 if (!cppmeth && !protoPair.empty() && protoPair != proto) {
267 std::string resname =
273 if (resname.find(
"initializer_list") != std::string::npos) {
274 auto pos = proto.find(
"initializer_list");
275 while (pos != std::string::npos) {
276 proto.replace(pos, 16,
"vector");
277 pos = proto.find(
"initializer_list", pos + 6);
282 if (m2 && m2 != cppmeth) {
290 bool bExactMatch = fname == resname;
295 PyObject* pycachename = PyUnicode_InternFromString(fname.c_str());
296 PyObject* pyol = PyObject_GetItem(dct, pycachename);
304 PyObject* pyresname = PyUnicode_FromString(resname.c_str());
306 exact = PyObject_GetItem(dct, pyresname);
312 bool bIsConstructor =
false, bNeedsRebind =
true;
317 bNeedsRebind =
false;
320 bNeedsRebind =
false;
322 bIsConstructor =
true;
331 if (bIsConstructor) {
338 PyType_Type.tp_setattro(
fTI->fPyClass, pycachename, pyol);
365 if (!exact && !bExactMatch) {
366 PyType_Type.tp_setattro(
fTI->fPyClass, pyresname, pyol);
371 Py_DECREF(pyresname);
372 Py_DECREF(pycachename);
381 PyErr_Format(PyExc_TypeError,
"Failed to instantiate \"%s(%s)\"",
382 fname.c_str(), proto.c_str());
390 pytmpl->
fSelf =
nullptr;
394 pytmpl->
fTI = std::make_shared<TemplateInfo>();
396 PyObject_GC_Track(pytmpl);
405 if (op == Py_EQ || op == Py_NE) {
415 Py_INCREF(Py_NotImplemented);
416 return Py_NotImplemented;
422 Py_CLEAR(pytmpl->
fSelf);
432 PyObject_ClearWeakRefs((
PyObject*)pytmpl);
433 PyObject_GC_UnTrack(pytmpl);
435 pytmpl->
fTI.~TP_TInfo_t();
436 PyObject_GC_Del(pytmpl);
442 Py_VISIT(pytmpl->
fSelf);
450 if (pytmpl->
fTI->fDoc) {
451 Py_INCREF(pytmpl->
fTI->fDoc);
452 return pytmpl->
fTI->fDoc;
457 if (pytmpl->
fTI->fNonTemplated->HasMethods())
458 doc = PyObject_GetAttrString((
PyObject*)pytmpl->
fTI->fNonTemplated,
460 if (pytmpl->
fTI->fTemplated->HasMethods()) {
462 PyObject_GetAttrString((
PyObject*)pytmpl->
fTI->fTemplated,
"__doc__");
464 PyUnicode_AppendAndDel(&doc, PyUnicode_FromString(
"\n"));
465 PyUnicode_AppendAndDel(&doc, doc2);
466 }
else if (!doc && doc2) {
470 if (pytmpl->
fTI->fLowPriority->HasMethods()) {
472 PyObject_GetAttrString((
PyObject*)pytmpl->
fTI->fLowPriority,
"__doc__");
474 PyUnicode_AppendAndDel(&doc, PyUnicode_FromString(
"\n"));
475 PyUnicode_AppendAndDel(&doc, doc2);
476 }
else if (!doc && doc2) {
488 Py_XDECREF(pytmpl->
fTI->fDoc);
490 pytmpl->
fTI->fDoc = val;
498#define TPPCALL_RETURN \
508 bool bInserted =
false;
509 auto&
v = pytmpl->
fTI->fDispatchMap[use_targs ?
targs2str(pytmpl) :
""];
513 if (
p.first == sighash) {
520 v.push_back(std::make_pair(sighash, pymeth));
526 bool implicitOkay,
bool use_targs, uint64_t sighash,
527 std::vector<Utility::PyError_t>& errors) {
561 if (isNS && pytmpl->
fSelf && pytmpl->
fSelf != Py_None) {
622 auto&
v = pytmpl->
fTI->fDispatchMap[
""];
623 for (
const auto&
p :
v) {
624 if (
p.first == sighash) {
631 if (!pytmpl->
fSelf || pytmpl->
fSelf == Py_None) {
646 std::vector<Utility::PyError_t> errors;
653 PyObject* pyfullname = PyUnicode_FromString(pytmpl->
fTI->fCppName.c_str());
659 if (pytmpl->
fSelf && pytmpl->
fSelf != Py_None && !isNS)
660 pymeth = PyObject_GetAttr(pytmpl->
fSelf, pyfullname);
662 pymeth = PyType_Type.tp_getattro(pytmpl->
fTI->fPyClass, pyfullname);
671 Py_DECREF(pyfullname);
675 }
else if (pymeth && PyCallable_Check(pymeth)) {
680 Py_DECREF(pyfullname);
688 pymeth = pytmpl->
Instantiate(PyUnicode_AsUTF8(pyfullname), args, nargsf,
696 Py_DECREF(pyfullname);
704 PyObject* topmsg = PyUnicode_FromFormat(
705 "Could not find \"%s\" (set cppjit.set_debug() for C++ errors):",
706 PyUnicode_AsUTF8(pyfullname));
707 Py_DECREF(pyfullname);
717 false , sighash, errors);
734 pytmpl->
Instantiate(pytmpl->
fTI->fCppName, args, nargsf, pref, &pcnt);
751 false , sighash, errors);
757 if (!errors.empty()) {
759 PyUnicode_FromString(
"Template method resolution failed:");
763 PyErr_Format(PyExc_TypeError,
764 "cannot resolve method template call for \'%s\'",
765 pytmpl->
fTI->fCppName.c_str());
781 newPyTmpl->
fSelf = pyobj;
784 newPyTmpl->
fSelf = Py_None;
791 new (&newPyTmpl->
fTI) std::shared_ptr<TemplateInfo>{pytmpl->
fTI};
810 if (PyErr_Occurred()) {
818 return PyLong_FromLong(0);
838 PyErr_SetString(PyExc_AttributeError,
"__template_args__ is read-only");
849 (
char*)
"unused",
nullptr},
852 (
char*)
"the template arguments for this method",
nullptr},
853 {(
char*)
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
863 fTI->fCppName = cppname;
865 fTI->fPyClass = pyclass;
867 std::vector<PyCallable*> dummy;
878 const char* sigarg =
nullptr;
879 const char* tmplarg =
nullptr;
887 if (PyArg_ParseTuple(args,
const_cast<char*
>(
"s|i:__overload__"), &sigarg,
889 want_const = PyTuple_GET_SIZE(args) == 1 ? -1 : want_const;
892 PyObject* ol = pytmpl->
fTI->fNonTemplated->FindOverload(sigarg, want_const);
896 ol = pytmpl->
fTI->fTemplated->FindOverload(sigarg, want_const);
900 ol = pytmpl->
fTI->fLowPriority->FindOverload(sigarg, want_const);
907 if (PyErr_Occurred()) {
911 scope = ((
CPPClass*)pytmpl->
fTI->fPyClass)->fCppType;
913 proto.substr(1, proto.size() - 2));
914 }
else if (PyArg_ParseTuple(args,
const_cast<char*
>(
"ss:__overload__"),
915 &sigarg, &tmplarg)) {
916 scope = ((
CPPClass*)pytmpl->
fTI->fPyClass)->fCppType;
917 std::string full_name =
918 std::string(pytmpl->
fTI->fCppName) +
"<" + tmplarg +
">";
921 }
else if (PyArg_ParseTuple(args,
const_cast<char*
>(
"O|i:__overload__"),
922 &sigarg_tuple, &want_const)) {
924 want_const = PyTuple_GET_SIZE(args) == 1 ? -1 : want_const;
928 pytmpl->
fTI->fNonTemplated->FindOverload(sigarg_tuple, want_const);
932 ol = pytmpl->
fTI->fTemplated->FindOverload(sigarg_tuple, want_const);
936 ol = pytmpl->
fTI->fLowPriority->FindOverload(sigarg_tuple, want_const);
941 proto.push_back(
'<');
942 Py_ssize_t
n = PyTuple_Size(sigarg_tuple);
943 for (
int i = 0; i <
n; i++) {
944 PyObject* pItem = PyTuple_GetItem(sigarg_tuple, i);
945 if (!PyUnicode_Check(pItem)) {
946 PyErr_Format(PyExc_LookupError,
947 "argument types should be in string format");
950 proto.append(PyUnicode_AsUTF8(pItem));
952 proto.push_back(
',');
954 proto.push_back(
'>');
956 scope = ((
CPPClass*)pytmpl->
fTI->fPyClass)->fCppType;
958 proto.substr(1, proto.size() - 2));
960 PyErr_Format(PyExc_TypeError,
"Unexpected arguments to __overload__");
987 (
char*)
"select overload for dispatch"},
988 {(
char*)
nullptr,
nullptr, 0,
nullptr}};
992 PyVarObject_HEAD_INIT(&PyType_Type,
993 0)(
char*)
"cppjit.TemplateProxy",
1006 (ternaryfunc)PyVectorcall_Call,
1012 Py_TPFLAGS_METHOD_DESCRIPTOR,
1013 (
char*)
"cppjit template proxy (internal)",
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
void AdoptMethod(PyCallable *pc)
void MergeOverload(CPPOverload *meth)
MethodInfo_t * fMethodInfo
virtual bool IsGreedy()=0
virtual PyCallable * Clone()=0
CPPOverload * fLowPriority
CPPOverload * fNonTemplated
TP_DispatchMap_t fDispatchMap
void AdoptTemplate(PyCallable *pc)
void Set(const std::string &cppname, const std::string &pyname, PyObject *pyclass)
PyObject * Instantiate(const std::string &fname, cpyrt_PyArgs_t tmplArgs, size_t nargsf, Utility::ArgPreference, int *pcnt=nullptr)
void AdoptMethod(PyCallable *pc)
PyObject_HEAD PyObject * fSelf
void MergeOverload(CPPOverload *mp)
vectorcallfunc fVectorCall
PyObject *const * cpyrt_PyArgs_t
static Py_ssize_t cpyrt_PyArgs_GET_SIZE(cpyrt_PyArgs_t, size_t nargsf)
PyObject * cpyrt_tp_call(PyObject *cb, cpyrt_PyArgs_t args, size_t nargsf, PyObject *kwds)
#define Py_TPFLAGS_HAVE_VECTORCALL
#define CPYRT_PYTYPE_TAIL
#define cpyrt_PyObject_Call
static PyObject * cpyrt_PyArgs_GET_ITEM(cpyrt_PyArgs_t args, Py_ssize_t i)
std::string ConstructTemplateArgs(PyObject *pyname, PyObject *tpArgs, PyObject *args=nullptr, ArgPreference=kNone, int argoff=0, int *pcnt=nullptr)
size_t FetchError(std::vector< PyError_t > &, bool is_cpp=false)
void SetDetailedException(std::vector< PyError_t > &&errors, PyObject *topmsg, PyObject *defexc)
PyObject * CT2CppName(PyObject *pytc, const char *cpd, bool allow_voidp)
bool CPPOverload_Check(T *object)
bool TemplateProxy_Check(T *object)
static void tpp_dealloc(TemplateProxy *pytmpl)
static int tpp_settemplateargs(TemplateProxy *, PyObject *, void *)
static PyMethodDef tpp_methods[]
static PyGetSetDef tpp_getset[]
static TemplateProxy * tpp_new(PyTypeObject *, PyObject *, PyObject *)
static void UpdateDispatchMap(TemplateProxy *pytmpl, bool use_targs, uint64_t sighash, CPPOverload *pymeth)
bool AdjustSelf(PyCallArgs &cargs)
static PyObject * tpp_vectorcall(TemplateProxy *pytmpl, PyObject *const *args, size_t nargsf, PyObject *kwds)
uint64_t HashSignature(cpyrt_PyArgs_t args, size_t nargsf)
static int tpp_setuseffi(CPPOverload *, PyObject *, void *)
PyTypeObject CPPOverload_Type
static PyObject * tpp_gettemplateargs(TemplateProxy *self, void *)
static int tpp_clear(TemplateProxy *pytmpl)
static PyObject * tpp_getuseffi(CPPOverload *, void *)
static std::string targs2str(TemplateProxy *pytmpl)
static PyObject * SelectAndForward(TemplateProxy *pytmpl, CPPOverload *pymeth, cpyrt_PyArgs_t args, size_t nargsf, PyObject *kwds, bool implicitOkay, bool use_targs, uint64_t sighash, std::vector< Utility::PyError_t > &errors)
PyTypeObject TemplateProxy_Type
static int tpp_doc_set(TemplateProxy *pytmpl, PyObject *val, void *)
static PyObject * tpp_subscript(TemplateProxy *pytmpl, PyObject *args)
static TemplateProxy * tpp_descr_get(TemplateProxy *pytmpl, PyObject *pyobj, PyObject *)
static Py_hash_t tpp_hash(TemplateProxy *self)
bool TemplateProxy_CheckExact(T *object)
static PyMappingMethods tpp_as_mapping
std::shared_ptr< TemplateInfo > TP_TInfo_t
static int tpp_traverse(TemplateProxy *pytmpl, visitproc visit, void *arg)
static PyObject * tpp_richcompare(TemplateProxy *self, PyObject *other, int op)
CPPOverload * CPPOverload_New(const std::string &name, std::vector< PyCallable * > &methods)
static PyObject * CallMethodImp(TemplateProxy *pytmpl, PyObject *&pymeth, cpyrt_PyArgs_t args, size_t nargsf, PyObject *kwds, bool impOK, uint64_t sighash)
static PyObject * tpp_doc(TemplateProxy *pytmpl, void *)
static PyObject * tpp_overload(TemplateProxy *pytmpl, PyObject *args)
TCppMethod_t GetMethodTemplate(TCppScope_t scope, const std::string &name, const std::string &proto)
bool IsStaticTemplate(TCppScope_t scope, const std::string &name)
bool IsConstructor(TCppMethod_t method)
Cpp::FuncRef TCppMethod_t
std::string GetFullName(TCppScope_t)
bool IsNamespace(TCppScope_t scope)
bool IsStaticMethod(TCppMethod_t method)
CPPOverload::Methods_t fMethods