1 // Mypyc C API
2 
3 #ifndef CPY_CPY_H
4 #define CPY_CPY_H
5 
6 #include <stdbool.h>
7 #include <Python.h>
8 #include <frameobject.h>
9 #include <structmember.h>
10 #include <assert.h>
11 #include <stdint.h>
12 #include "pythonsupport.h"
13 #include "mypyc_util.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 #if 0
19 } // why isn't emacs smart enough to not indent this
20 #endif
21 
22 #define CPYTHON_LARGE_INT_ERRMSG "Python int too large to convert to C ssize_t"
23 
24 
25 // Naming conventions:
26 //
27 // Tagged: tagged int
28 // Long: tagged long int (pointer)
29 // Short: tagged short int (unboxed)
30 // Ssize_t: A Py_ssize_t, which ought to be the same width as pointers
31 // Object: CPython object (PyObject *)
32 
33 
34 // Tuple type definitions needed for API functions
35 
36 
37 #ifndef MYPYC_DECLARED_tuple_T3OOO
38 #define MYPYC_DECLARED_tuple_T3OOO
39 typedef struct tuple_T3OOO {
40     PyObject *f0;
41     PyObject *f1;
42     PyObject *f2;
43 } tuple_T3OOO;
44 static tuple_T3OOO tuple_undefined_T3OOO = { NULL, NULL, NULL };
45 #endif
46 
47 // Our return tuple wrapper for dictionary iteration helper.
48 #ifndef MYPYC_DECLARED_tuple_T3CIO
49 #define MYPYC_DECLARED_tuple_T3CIO
50 typedef struct tuple_T3CIO {
51     char f0;  // Should continue?
52     CPyTagged f1;  // Last dict offset
53     PyObject *f2;  // Next dictionary key or value
54 } tuple_T3CIO;
55 static tuple_T3CIO tuple_undefined_T3CIO = { 2, CPY_INT_TAG, NULL };
56 #endif
57 
58 // Same as above but for both key and value.
59 #ifndef MYPYC_DECLARED_tuple_T4CIOO
60 #define MYPYC_DECLARED_tuple_T4CIOO
61 typedef struct tuple_T4CIOO {
62     char f0;  // Should continue?
63     CPyTagged f1;  // Last dict offset
64     PyObject *f2;  // Next dictionary key
65     PyObject *f3;  // Next dictionary value
66 } tuple_T4CIOO;
67 static tuple_T4CIOO tuple_undefined_T4CIOO = { 2, CPY_INT_TAG, NULL, NULL };
68 #endif
69 
70 
71 // Native object operations
72 
73 
74 // Search backwards through the trait part of a vtable (which sits *before*
75 // the start of the vtable proper) looking for the subvtable describing a trait
76 // implementation. We don't do any bounds checking so we'd better be pretty sure
77 // we know that it is there.
CPy_FindTraitVtable(PyTypeObject * trait,CPyVTableItem * vtable)78 static inline CPyVTableItem *CPy_FindTraitVtable(PyTypeObject *trait, CPyVTableItem *vtable) {
79     int i;
80     for (i = -3; ; i -= 3) {
81         if ((PyTypeObject *)vtable[i] == trait) {
82             return (CPyVTableItem *)vtable[i + 1];
83         }
84     }
85 }
86 
87 // Use the same logic for offset table.
CPy_FindAttrOffset(PyTypeObject * trait,CPyVTableItem * vtable,size_t index)88 static inline size_t CPy_FindAttrOffset(PyTypeObject *trait, CPyVTableItem *vtable, size_t index) {
89     int i;
90     for (i = -3; ; i -= 3) {
91         if ((PyTypeObject *)vtable[i] == trait) {
92             return ((size_t *)vtable[i + 2])[index];
93         }
94     }
95 }
96 
97 // Get attribute value using vtable (may return an undefined value)
98 #define CPY_GET_ATTR(obj, type, vtable_index, object_type, attr_type)    \
99     ((attr_type (*)(object_type *))((object_type *)obj)->vtable[vtable_index])((object_type *)obj)
100 
101 #define CPY_GET_ATTR_TRAIT(obj, trait, vtable_index, object_type, attr_type)   \
102     ((attr_type (*)(object_type *))(CPy_FindTraitVtable(trait, ((object_type *)obj)->vtable))[vtable_index])((object_type *)obj)
103 
104 // Set attribute value using vtable
105 #define CPY_SET_ATTR(obj, type, vtable_index, value, object_type, attr_type) \
106     ((bool (*)(object_type *, attr_type))((object_type *)obj)->vtable[vtable_index])( \
107         (object_type *)obj, value)
108 
109 #define CPY_SET_ATTR_TRAIT(obj, trait, vtable_index, value, object_type, attr_type) \
110     ((bool (*)(object_type *, attr_type))(CPy_FindTraitVtable(trait, ((object_type *)obj)->vtable))[vtable_index])( \
111         (object_type *)obj, value)
112 
113 #define CPY_GET_METHOD(obj, type, vtable_index, object_type, method_type) \
114     ((method_type)(((object_type *)obj)->vtable[vtable_index]))
115 
116 #define CPY_GET_METHOD_TRAIT(obj, trait, vtable_index, object_type, method_type) \
117     ((method_type)(CPy_FindTraitVtable(trait, ((object_type *)obj)->vtable)[vtable_index]))
118 
119 
120 // Int operations
121 
122 
123 CPyTagged CPyTagged_FromSsize_t(Py_ssize_t value);
124 CPyTagged CPyTagged_FromObject(PyObject *object);
125 CPyTagged CPyTagged_StealFromObject(PyObject *object);
126 CPyTagged CPyTagged_BorrowFromObject(PyObject *object);
127 PyObject *CPyTagged_AsObject(CPyTagged x);
128 PyObject *CPyTagged_StealAsObject(CPyTagged x);
129 Py_ssize_t CPyTagged_AsSsize_t(CPyTagged x);
130 void CPyTagged_IncRef(CPyTagged x);
131 void CPyTagged_DecRef(CPyTagged x);
132 void CPyTagged_XDecRef(CPyTagged x);
133 CPyTagged CPyTagged_Negate(CPyTagged num);
134 CPyTagged CPyTagged_Invert(CPyTagged num);
135 CPyTagged CPyTagged_Add(CPyTagged left, CPyTagged right);
136 CPyTagged CPyTagged_Subtract(CPyTagged left, CPyTagged right);
137 CPyTagged CPyTagged_Multiply(CPyTagged left, CPyTagged right);
138 CPyTagged CPyTagged_FloorDivide(CPyTagged left, CPyTagged right);
139 CPyTagged CPyTagged_Remainder(CPyTagged left, CPyTagged right);
140 CPyTagged CPyTagged_And(CPyTagged left, CPyTagged right);
141 CPyTagged CPyTagged_Or(CPyTagged left, CPyTagged right);
142 CPyTagged CPyTagged_Xor(CPyTagged left, CPyTagged right);
143 CPyTagged CPyTagged_Rshift(CPyTagged left, CPyTagged right);
144 CPyTagged CPyTagged_Lshift(CPyTagged left, CPyTagged right);
145 bool CPyTagged_IsEq_(CPyTagged left, CPyTagged right);
146 bool CPyTagged_IsLt_(CPyTagged left, CPyTagged right);
147 PyObject *CPyTagged_Str(CPyTagged n);
148 PyObject *CPyLong_FromStrWithBase(PyObject *o, CPyTagged base);
149 PyObject *CPyLong_FromStr(PyObject *o);
150 PyObject *CPyLong_FromFloat(PyObject *o);
151 PyObject *CPyBool_Str(bool b);
152 
CPyTagged_CheckLong(CPyTagged x)153 static inline int CPyTagged_CheckLong(CPyTagged x) {
154     return x & CPY_INT_TAG;
155 }
156 
CPyTagged_CheckShort(CPyTagged x)157 static inline int CPyTagged_CheckShort(CPyTagged x) {
158     return !CPyTagged_CheckLong(x);
159 }
160 
CPyTagged_ShortAsSsize_t(CPyTagged x)161 static inline Py_ssize_t CPyTagged_ShortAsSsize_t(CPyTagged x) {
162     // NOTE: Assume that we sign extend.
163     return (Py_ssize_t)x >> 1;
164 }
165 
CPyTagged_LongAsObject(CPyTagged x)166 static inline PyObject *CPyTagged_LongAsObject(CPyTagged x) {
167     // NOTE: Assume target is not a short int.
168     return (PyObject *)(x & ~CPY_INT_TAG);
169 }
170 
CPyTagged_TooBig(Py_ssize_t value)171 static inline bool CPyTagged_TooBig(Py_ssize_t value) {
172     // Micro-optimized for the common case where it fits.
173     return (size_t)value > CPY_TAGGED_MAX
174         && (value >= 0 || value < CPY_TAGGED_MIN);
175 }
176 
CPyTagged_IsAddOverflow(CPyTagged sum,CPyTagged left,CPyTagged right)177 static inline bool CPyTagged_IsAddOverflow(CPyTagged sum, CPyTagged left, CPyTagged right) {
178     // This check was copied from some of my old code I believe that it works :-)
179     return (Py_ssize_t)(sum ^ left) < 0 && (Py_ssize_t)(sum ^ right) < 0;
180 }
181 
CPyTagged_IsSubtractOverflow(CPyTagged diff,CPyTagged left,CPyTagged right)182 static inline bool CPyTagged_IsSubtractOverflow(CPyTagged diff, CPyTagged left, CPyTagged right) {
183     // This check was copied from some of my old code I believe that it works :-)
184     return (Py_ssize_t)(diff ^ left) < 0 && (Py_ssize_t)(diff ^ right) >= 0;
185 }
186 
CPyTagged_IsMultiplyOverflow(CPyTagged left,CPyTagged right)187 static inline bool CPyTagged_IsMultiplyOverflow(CPyTagged left, CPyTagged right) {
188     // This is conservative -- return false only in a small number of all non-overflow cases
189     return left >= (1U << (CPY_INT_BITS/2 - 1)) || right >= (1U << (CPY_INT_BITS/2 - 1));
190 }
191 
CPyTagged_MaybeFloorDivideFault(CPyTagged left,CPyTagged right)192 static inline bool CPyTagged_MaybeFloorDivideFault(CPyTagged left, CPyTagged right) {
193     return right == 0 || left == -((size_t)1 << (CPY_INT_BITS-1));
194 }
195 
CPyTagged_MaybeRemainderFault(CPyTagged left,CPyTagged right)196 static inline bool CPyTagged_MaybeRemainderFault(CPyTagged left, CPyTagged right) {
197     // Division/modulus can fault when dividing INT_MIN by -1, but we
198     // do our mods on still-tagged integers with the low-bit clear, so
199     // -1 is actually represented as -2 and can't overflow.
200     // Mod by 0 can still fault though.
201     return right == 0;
202 }
203 
CPyTagged_IsEq(CPyTagged left,CPyTagged right)204 static inline bool CPyTagged_IsEq(CPyTagged left, CPyTagged right) {
205     if (CPyTagged_CheckShort(left)) {
206         return left == right;
207     } else {
208         return CPyTagged_IsEq_(left, right);
209     }
210 }
211 
CPyTagged_IsNe(CPyTagged left,CPyTagged right)212 static inline bool CPyTagged_IsNe(CPyTagged left, CPyTagged right) {
213     if (CPyTagged_CheckShort(left)) {
214         return left != right;
215     } else {
216         return !CPyTagged_IsEq_(left, right);
217     }
218 }
219 
CPyTagged_IsLt(CPyTagged left,CPyTagged right)220 static inline bool CPyTagged_IsLt(CPyTagged left, CPyTagged right) {
221     if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right)) {
222         return (Py_ssize_t)left < (Py_ssize_t)right;
223     } else {
224         return CPyTagged_IsLt_(left, right);
225     }
226 }
227 
CPyTagged_IsGe(CPyTagged left,CPyTagged right)228 static inline bool CPyTagged_IsGe(CPyTagged left, CPyTagged right) {
229     if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right)) {
230         return (Py_ssize_t)left >= (Py_ssize_t)right;
231     } else {
232         return !CPyTagged_IsLt_(left, right);
233     }
234 }
235 
CPyTagged_IsGt(CPyTagged left,CPyTagged right)236 static inline bool CPyTagged_IsGt(CPyTagged left, CPyTagged right) {
237     if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right)) {
238         return (Py_ssize_t)left > (Py_ssize_t)right;
239     } else {
240         return CPyTagged_IsLt_(right, left);
241     }
242 }
243 
CPyTagged_IsLe(CPyTagged left,CPyTagged right)244 static inline bool CPyTagged_IsLe(CPyTagged left, CPyTagged right) {
245     if (CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right)) {
246         return (Py_ssize_t)left <= (Py_ssize_t)right;
247     } else {
248         return !CPyTagged_IsLt_(right, left);
249     }
250 }
251 
252 
253 // Generic operations (that work with arbitrary types)
254 
255 
256 /* We use intentionally non-inlined decrefs since it pretty
257  * substantially speeds up compile time while only causing a ~1%
258  * performance degradation. We have our own copies both to avoid the
259  * null check in Py_DecRef and to avoid making an indirect PIC
260  * call. */
261 CPy_NOINLINE
CPy_DecRef(PyObject * p)262 static void CPy_DecRef(PyObject *p) {
263     CPy_DECREF(p);
264 }
265 
266 CPy_NOINLINE
CPy_XDecRef(PyObject * p)267 static void CPy_XDecRef(PyObject *p) {
268     CPy_XDECREF(p);
269 }
270 
CPyObject_Size(PyObject * obj)271 static inline CPyTagged CPyObject_Size(PyObject *obj) {
272     Py_ssize_t s = PyObject_Size(obj);
273     if (s < 0) {
274         return CPY_INT_TAG;
275     } else {
276         // Technically __len__ could return a really big number, so we
277         // should allow this to produce a boxed int. In practice it
278         // shouldn't ever if the data structure actually contains all
279         // the elements, but...
280         return CPyTagged_FromSsize_t(s);
281     }
282 }
283 
284 #ifdef MYPYC_LOG_GETATTR
CPy_LogGetAttr(const char * method,PyObject * obj,PyObject * attr)285 static void CPy_LogGetAttr(const char *method, PyObject *obj, PyObject *attr) {
286     PyObject *module = PyImport_ImportModule("getattr_hook");
287     if (module) {
288         PyObject *res = PyObject_CallMethod(module, method, "OO", obj, attr);
289         Py_XDECREF(res);
290         Py_DECREF(module);
291     }
292     PyErr_Clear();
293 }
294 #else
295 #define CPy_LogGetAttr(method, obj, attr) (void)0
296 #endif
297 
298 // Intercept a method call and log it. This needs to be a macro
299 // because there is no API that accepts va_args for making a
300 // call. Worse, it needs to use the comma operator to return the right
301 // value.
302 #define CPyObject_CallMethodObjArgs(obj, attr, ...)             \
303     (CPy_LogGetAttr("log_method", (obj), (attr)),               \
304      PyObject_CallMethodObjArgs((obj), (attr), __VA_ARGS__))
305 
306 // This one is a macro for consistency with the above, I guess.
307 #define CPyObject_GetAttr(obj, attr)                       \
308     (CPy_LogGetAttr("log", (obj), (attr)),                 \
309      PyObject_GetAttr((obj), (attr)))
310 
311 CPyTagged CPyObject_Hash(PyObject *o);
312 PyObject *CPyObject_GetAttr3(PyObject *v, PyObject *name, PyObject *defl);
313 PyObject *CPyIter_Next(PyObject *iter);
314 PyObject *CPyNumber_Power(PyObject *base, PyObject *index);
315 PyObject *CPyObject_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
316 
317 
318 // List operations
319 
320 
321 PyObject *CPyList_GetItem(PyObject *list, CPyTagged index);
322 PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index);
323 PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index);
324 bool CPyList_SetItem(PyObject *list, CPyTagged index, PyObject *value);
325 bool CPyList_SetItemUnsafe(PyObject *list, CPyTagged index, PyObject *value);
326 PyObject *CPyList_PopLast(PyObject *obj);
327 PyObject *CPyList_Pop(PyObject *obj, CPyTagged index);
328 CPyTagged CPyList_Count(PyObject *obj, PyObject *value);
329 int CPyList_Insert(PyObject *list, CPyTagged index, PyObject *value);
330 PyObject *CPyList_Extend(PyObject *o1, PyObject *o2);
331 int CPyList_Remove(PyObject *list, PyObject *obj);
332 CPyTagged CPyList_Index(PyObject *list, PyObject *obj);
333 PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size);
334 PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq);
335 PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
336 
337 
338 // Dict operations
339 
340 
341 PyObject *CPyDict_GetItem(PyObject *dict, PyObject *key);
342 int CPyDict_SetItem(PyObject *dict, PyObject *key, PyObject *value);
343 PyObject *CPyDict_Get(PyObject *dict, PyObject *key, PyObject *fallback);
344 PyObject *CPyDict_GetWithNone(PyObject *dict, PyObject *key);
345 PyObject *CPyDict_SetDefault(PyObject *dict, PyObject *key, PyObject *value);
346 PyObject *CPyDict_SetDefaultWithNone(PyObject *dict, PyObject *key);
347 PyObject *CPyDict_Build(Py_ssize_t size, ...);
348 int CPyDict_Update(PyObject *dict, PyObject *stuff);
349 int CPyDict_UpdateInDisplay(PyObject *dict, PyObject *stuff);
350 int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff);
351 PyObject *CPyDict_FromAny(PyObject *obj);
352 PyObject *CPyDict_KeysView(PyObject *dict);
353 PyObject *CPyDict_ValuesView(PyObject *dict);
354 PyObject *CPyDict_ItemsView(PyObject *dict);
355 PyObject *CPyDict_Keys(PyObject *dict);
356 PyObject *CPyDict_Values(PyObject *dict);
357 PyObject *CPyDict_Items(PyObject *dict);
358 char CPyDict_Clear(PyObject *dict);
359 PyObject *CPyDict_Copy(PyObject *dict);
360 PyObject *CPyDict_GetKeysIter(PyObject *dict);
361 PyObject *CPyDict_GetItemsIter(PyObject *dict);
362 PyObject *CPyDict_GetValuesIter(PyObject *dict);
363 tuple_T3CIO CPyDict_NextKey(PyObject *dict_or_iter, CPyTagged offset);
364 tuple_T3CIO CPyDict_NextValue(PyObject *dict_or_iter, CPyTagged offset);
365 tuple_T4CIOO CPyDict_NextItem(PyObject *dict_or_iter, CPyTagged offset);
366 
367 // Check that dictionary didn't change size during iteration.
CPyDict_CheckSize(PyObject * dict,CPyTagged size)368 static inline char CPyDict_CheckSize(PyObject *dict, CPyTagged size) {
369     if (!PyDict_CheckExact(dict)) {
370         // Dict subclasses will be checked by Python runtime.
371         return 1;
372     }
373     Py_ssize_t py_size = CPyTagged_AsSsize_t(size);
374     Py_ssize_t dict_size = PyDict_Size(dict);
375     if (py_size != dict_size) {
376         PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration");
377         return 0;
378     }
379     return 1;
380 }
381 
382 
383 // Str operations
384 
385 
386 PyObject *CPyStr_GetItem(PyObject *str, CPyTagged index);
387 PyObject *CPyStr_Split(PyObject *str, PyObject *sep, CPyTagged max_split);
388 PyObject *CPyStr_Replace(PyObject *str, PyObject *old_substr, PyObject *new_substr, CPyTagged max_replace);
389 PyObject *CPyStr_Append(PyObject *o1, PyObject *o2);
390 PyObject *CPyStr_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
391 bool CPyStr_Startswith(PyObject *self, PyObject *subobj);
392 bool CPyStr_Endswith(PyObject *self, PyObject *subobj);
393 bool CPyStr_IsTrue(PyObject *obj);
394 
395 
396 // Set operations
397 
398 
399 bool CPySet_Remove(PyObject *set, PyObject *key);
400 
401 
402 // Tuple operations
403 
404 
405 PyObject *CPySequenceTuple_GetItem(PyObject *tuple, CPyTagged index);
406 PyObject *CPySequenceTuple_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
407 bool CPySequenceTuple_SetItemUnsafe(PyObject *tuple, CPyTagged index, PyObject *value);
408 
409 
410 // Exception operations
411 
412 
413 // mypyc is not very good at dealing with refcount management of
414 // pointers that might be NULL. As a workaround for this, the
415 // exception APIs that might want to return NULL pointers instead
416 // return properly refcounted pointers to this dummy object.
417 struct ExcDummyStruct { PyObject_HEAD };
418 extern struct ExcDummyStruct _CPy_ExcDummyStruct;
419 extern PyObject *_CPy_ExcDummy;
420 
_CPy_ToDummy(PyObject ** p)421 static inline void _CPy_ToDummy(PyObject **p) {
422     if (*p == NULL) {
423         Py_INCREF(_CPy_ExcDummy);
424         *p = _CPy_ExcDummy;
425     }
426 }
427 
_CPy_FromDummy(PyObject * p)428 static inline PyObject *_CPy_FromDummy(PyObject *p) {
429     if (p == _CPy_ExcDummy) return NULL;
430     Py_INCREF(p);
431     return p;
432 }
433 
CPy_NoErrOccured(void)434 static int CPy_NoErrOccured(void) {
435     return PyErr_Occurred() == NULL;
436 }
437 
CPy_KeepPropagating(void)438 static inline bool CPy_KeepPropagating(void) {
439     return 0;
440 }
441 // We want to avoid the public PyErr_GetExcInfo API for these because
442 // it requires a bunch of spurious refcount traffic on the parts of
443 // the triple we don't care about. Unfortunately the layout of the
444 // data structure changed in 3.7 so we need to handle that.
445 #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 7
446 #define CPy_ExcState() PyThreadState_GET()->exc_info
447 #else
448 #define CPy_ExcState() PyThreadState_GET()
449 #endif
450 
451 void CPy_Raise(PyObject *exc);
452 void CPy_Reraise(void);
453 void CPyErr_SetObjectAndTraceback(PyObject *type, PyObject *value, PyObject *traceback);
454 tuple_T3OOO CPy_CatchError(void);
455 void CPy_RestoreExcInfo(tuple_T3OOO info);
456 bool CPy_ExceptionMatches(PyObject *type);
457 PyObject *CPy_GetExcValue(void);
458 tuple_T3OOO CPy_GetExcInfo(void);
459 void _CPy_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback);
460 void CPyError_OutOfMemory(void);
461 void CPy_TypeError(const char *expected, PyObject *value);
462 void CPy_AddTraceback(const char *filename, const char *funcname, int line, PyObject *globals);
463 
464 
465 // Misc operations
466 
467 #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 8
468 #define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN(op, dealloc)
469 #define CPy_TRASHCAN_END(op) Py_TRASHCAN_END
470 #else
471 #define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN(op)
472 #define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END(op)
473 #endif
474 
475 // Tweaked version of _PyArg_Parser in CPython
476 typedef struct CPyArg_Parser {
477     const char *format;
478     const char * const *keywords;
479     const char *fname;
480     const char *custom_msg;
481     int pos;               /* number of positional-only arguments */
482     int min;               /* minimal number of arguments */
483     int max;               /* maximal number of positional arguments */
484     int has_required_kws;  /* are there any keyword-only arguments? */
485     int required_kwonly_start;
486     int varargs;           /* does the function accept *args or **kwargs? */
487     PyObject *kwtuple;     /* tuple of keyword parameter names */
488     struct CPyArg_Parser *next;
489 } CPyArg_Parser;
490 
491 // mypy lets ints silently coerce to floats, so a mypyc runtime float
492 // might be an int also
CPyFloat_Check(PyObject * o)493 static inline bool CPyFloat_Check(PyObject *o) {
494     return PyFloat_Check(o) || PyLong_Check(o);
495 }
496 
497 // TODO: find an unified way to avoid inline functions in non-C back ends that can not
498 //       use inline functions
CPy_TypeCheck(PyObject * o,PyObject * type)499 static inline bool CPy_TypeCheck(PyObject *o, PyObject *type) {
500     return PyObject_TypeCheck(o, (PyTypeObject *)type);
501 }
502 
CPy_CalculateMetaclass(PyObject * type,PyObject * o)503 static inline PyObject *CPy_CalculateMetaclass(PyObject *type, PyObject *o) {
504     return (PyObject *)_PyType_CalculateMetaclass((PyTypeObject *)type, o);
505 }
506 
507 PyObject *CPy_GetCoro(PyObject *obj);
508 PyObject *CPyIter_Send(PyObject *iter, PyObject *val);
509 int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp);
510 PyObject *CPy_FetchStopIterationValue(void);
511 PyObject *CPyType_FromTemplate(PyObject *template_,
512                                PyObject *orig_bases,
513                                PyObject *modname);
514 PyObject *CPyType_FromTemplateWarpper(PyObject *template_,
515                                       PyObject *orig_bases,
516                                       PyObject *modname);
517 int CPyDataclass_SleightOfHand(PyObject *dataclass_dec, PyObject *tp,
518                                PyObject *dict, PyObject *annotations);
519 PyObject *CPyPickle_SetState(PyObject *obj, PyObject *state);
520 PyObject *CPyPickle_GetState(PyObject *obj);
521 CPyTagged CPyTagged_Id(PyObject *o);
522 void CPyDebug_Print(const char *msg);
523 void CPy_Init(void);
524 int CPyArg_ParseTupleAndKeywords(PyObject *, PyObject *,
525                                  const char *, const char *, const char * const *, ...);
526 int CPyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,
527                                  CPyArg_Parser *parser, ...);
528 int CPyArg_ParseStackAndKeywordsNoArgs(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,
529                                        CPyArg_Parser *parser, ...);
530 int CPyArg_ParseStackAndKeywordsOneArg(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,
531                                        CPyArg_Parser *parser, ...);
532 int CPyArg_ParseStackAndKeywordsSimple(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames,
533                                        CPyArg_Parser *parser, ...);
534 
535 int CPySequence_CheckUnpackCount(PyObject *sequence, Py_ssize_t expected);
536 int CPyStatics_Initialize(PyObject **statics,
537                           const char * const *strings,
538                           const char * const *bytestrings,
539                           const char * const *ints,
540                           const double *floats,
541                           const double *complex_numbers,
542                           const int *tuples);
543 PyObject *CPy_Super(PyObject *builtins, PyObject *self);
544 
545 #ifdef __cplusplus
546 }
547 #endif
548 
549 #endif // CPY_CPY_H
550