Nuitka
The Python compiler
Loading...
Searching...
No Matches
CompiledMethodType.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
10// This file is included from another C file, help IDEs to still parse it on
11// its own.
12#ifdef __IDE_ONLY__
13#include "nuitka/freelists.h"
14#include "nuitka/prelude.h"
15#include <structmember.h>
16#endif
17
18static PyObject *Nuitka_Method_get__doc__(PyObject *self, void *data) {
19 struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)self;
20 PyObject *result = method->m_function->m_doc;
21
22 if (result == NULL) {
23 result = Py_None;
24 }
25
26 Py_INCREF(result);
27 return result;
28}
29
30static PyGetSetDef Nuitka_Method_tp_getset[] = {{(char *)"__doc__", Nuitka_Method_get__doc__, NULL, NULL}, {NULL}};
31
32#define OFF(x) offsetof(struct Nuitka_MethodObject, x)
33
34static PyMemberDef Nuitka_Method_members[] = {
35 {(char *)"im_class", T_OBJECT, OFF(m_class), READONLY | RESTRICTED, (char *)"the class associated with a method"},
36 {(char *)"im_func", T_OBJECT, OFF(m_function), READONLY | RESTRICTED,
37 (char *)"the function (or other callable) implementing a method"},
38 {(char *)"__func__", T_OBJECT, OFF(m_function), READONLY | RESTRICTED,
39 (char *)"the function (or other callable) implementing a method"},
40 {(char *)"im_self", T_OBJECT, OFF(m_object), READONLY | RESTRICTED,
41 (char *)"the instance to which a method is bound; None for unbound method"},
42 {(char *)"__self__", T_OBJECT, OFF(m_object), READONLY | RESTRICTED,
43 (char *)"the instance to which a method is bound; None for unbound method"},
44 {NULL}};
45
46static PyObject *Nuitka_Method_reduce(struct Nuitka_MethodObject *method, PyObject *unused) {
47 PyThreadState *tstate = PyThreadState_GET();
48
49#if PYTHON_VERSION < 0x300
50 // spell-checker: ignore instancemethod
51 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "can't pickle instancemethod objects");
52 return NULL;
53#else
54 PyObject *result = MAKE_TUPLE_EMPTY(tstate, 2);
55 PyTuple_SET_ITEM0(result, 0, LOOKUP_BUILTIN(const_str_plain_getattr));
56 PyObject *arg_tuple = MAKE_TUPLE2(tstate, method->m_object, method->m_function->m_name);
57 PyTuple_SET_ITEM(result, 1, arg_tuple);
58
59 CHECK_OBJECT_DEEP(result);
60
61 return result;
62#endif
63}
64
65static PyObject *Nuitka_Method_reduce_ex(struct Nuitka_MethodObject *method, PyObject *args) {
66 int proto;
67
68 if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) {
69 return NULL;
70 }
71
72 // Python API, spell-checker: ignore copyreg,newobj
73
74#if PYTHON_VERSION < 0x300
75 PyObject *copy_reg = PyImport_ImportModule("copy_reg");
76
77 CHECK_OBJECT(copy_reg);
78 PyThreadState *tstate = PyThreadState_GET();
79
80 PyObject *newobj_func = LOOKUP_ATTRIBUTE(tstate, copy_reg, const_str_plain___newobj__);
81 Py_DECREF(copy_reg);
82 if (unlikely(newobj_func == NULL)) {
83 return NULL;
84 }
85
86 PyObject *result = MAKE_TUPLE_EMPTY(tstate, 5);
87 PyTuple_SET_ITEM(result, 0, newobj_func);
88 PyObject *type_tuple = MAKE_TUPLE1(tstate, (PyObject *)&Nuitka_Method_Type);
89 PyTuple_SET_ITEM(result, 1, type_tuple);
90 PyTuple_SET_ITEM_IMMORTAL(result, 2, Py_None);
91 PyTuple_SET_ITEM_IMMORTAL(result, 3, Py_None);
92 PyTuple_SET_ITEM_IMMORTAL(result, 4, Py_None);
93
94 CHECK_OBJECT_DEEP(result);
95
96 return result;
97#else
98 return Nuitka_Method_reduce(method, NULL);
99#endif
100}
101
102static PyObject *Nuitka_Method_deepcopy(struct Nuitka_MethodObject *method, PyObject *memo) {
103 assert(Nuitka_Method_Check((PyObject *)method));
104
105 static PyObject *module_copy = NULL;
106 static PyObject *deepcopy_function = NULL;
107
108 if (module_copy == NULL) {
109 module_copy = PyImport_ImportModule("copy");
110 CHECK_OBJECT(module_copy);
111
112 deepcopy_function = PyObject_GetAttrString(module_copy, "deepcopy");
113 CHECK_OBJECT(deepcopy_function);
114 }
115
116 PyObject *object = PyObject_CallFunctionObjArgs(deepcopy_function, method->m_object, memo, NULL);
117
118 if (unlikely(object == NULL)) {
119 return NULL;
120 }
121
122 PyObject *result = Nuitka_Method_New(method->m_function, object, method->m_class);
123 // Nuitka_Method_New took a reference to the object.
124 Py_DECREF(object);
125 return result;
126}
127
128static PyMethodDef Nuitka_Method_methods[] = {
129 {"__reduce__", (PyCFunction)Nuitka_Method_reduce, METH_NOARGS, NULL},
130 {"__reduce_ex__", (PyCFunction)Nuitka_Method_reduce_ex, METH_VARARGS, NULL},
131 {"__deepcopy__", (PyCFunction)Nuitka_Method_deepcopy, METH_O, NULL},
132 {NULL}};
133
134#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
135static PyObject *Nuitka_Method_tp_vectorcall(struct Nuitka_MethodObject *method, PyObject *const *stack, size_t nargsf,
136 PyObject *kwnames) {
137 assert(Nuitka_Method_Check((PyObject *)method));
138 assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
139 Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
140 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
141
142 assert(nargs >= 0);
143 assert((nargs == 0 && nkwargs == 0) || stack != NULL);
144
145 Py_ssize_t totalargs = nargs + nkwargs;
146
147 // Shortcut possible, no args.
148 if (totalargs == 0) {
149 return Nuitka_CallMethodFunctionNoArgs(PyThreadState_GET(), method->m_function, method->m_object);
150 }
151
152 PyObject *result;
153
154 if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
155 /* We are allowed to mutate the stack. TODO: Is this the normal case, so
156 we can consider the else branch irrelevant? Also does it not make sense
157 to check pos arg and kw counts and shortcut somewhat. */
158
159 PyObject **new_args = (PyObject **)stack - 1;
160
161 PyObject *tmp = new_args[0];
162 new_args[0] = method->m_object;
163
164 CHECK_OBJECTS(new_args, totalargs + 1);
165
166 result = Nuitka_CallFunctionVectorcall(PyThreadState_GET(), method->m_function, new_args, nargs + 1,
167 kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs);
168
169 CHECK_OBJECTS(new_args, totalargs + 1);
170
171 new_args[0] = tmp;
172 } else {
173 /* Definitely having args at this point. */
174 assert(stack != NULL);
175
176 NUITKA_DYNAMIC_ARRAY_DECL(new_args, PyObject *, totalargs + 1);
177 new_args[0] = method->m_object;
178 memcpy(&new_args[1], stack, totalargs * sizeof(PyObject *));
179
180 CHECK_OBJECTS(new_args, totalargs + 1);
181
182 result = Nuitka_CallFunctionVectorcall(PyThreadState_GET(), method->m_function, new_args, nargs + 1,
183 kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs);
184
185 CHECK_OBJECTS(new_args, totalargs + 1);
186 }
187
188 return result;
189}
190#endif
191
192static PyObject *Nuitka_Method_tp_call(struct Nuitka_MethodObject *method, PyObject *args, PyObject *kw) {
193 Py_ssize_t arg_count = PyTuple_GET_SIZE(args);
194
195 if (method->m_object == NULL) {
196 if (unlikely(arg_count < 1)) {
197 PyErr_Format(
198 PyExc_TypeError,
199 "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)",
200 GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function),
201 GET_CLASS_NAME(method->m_class));
202 return NULL;
203 } else {
204 PyObject *self = PyTuple_GET_ITEM(args, 0);
205 CHECK_OBJECT(self);
206
207 int result = PyObject_IsInstance(self, method->m_class);
208
209 if (unlikely(result < 0)) {
210 return NULL;
211 } else if (unlikely(result == 0)) {
212 PyThreadState *tstate = PyThreadState_GET();
213
214 PyErr_Format(PyExc_TypeError,
215 "unbound compiled_method %s%s must be called with %s instance as first argument (got %s "
216 "instance instead)",
217 GET_CALLABLE_NAME((PyObject *)method->m_function),
218 GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class),
219 GET_INSTANCE_CLASS_NAME(tstate, (PyObject *)self));
220
221 return NULL;
222 }
223 }
224
225 return Py_TYPE(method->m_function)->tp_call((PyObject *)method->m_function, args, kw);
226 } else {
227 PyThreadState *tstate = PyThreadState_GET();
228
229 if (kw == NULL) {
230 if (arg_count == 0) {
231 return Nuitka_CallMethodFunctionNoArgs(tstate, method->m_function, method->m_object);
232 } else {
233 return Nuitka_CallMethodFunctionPosArgs(tstate, method->m_function, method->m_object,
234 &PyTuple_GET_ITEM(args, 0), arg_count);
235 }
236 } else {
237 return Nuitka_CallMethodFunctionPosArgsKwArgs(tstate, method->m_function, method->m_object,
238 &PyTuple_GET_ITEM(args, 0), arg_count, kw);
239 }
240 }
241}
242
243#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
244static PyObject *Nuitka_Method_tp_descr_get(struct Nuitka_MethodObject *method, PyObject *object,
245 PyObject *class_object) {
246 // Don't rebind already bound methods.
247 if (method->m_object != NULL) {
248 Py_INCREF(method);
249 return (PyObject *)method;
250 }
251
252 if (method->m_class != NULL && class_object != NULL) {
253 // Quick subclass test, bound methods remain the same if the class is a sub class
254 int result = PyObject_IsSubclass(class_object, method->m_class);
255
256 if (unlikely(result < 0)) {
257 return NULL;
258 } else if (result == 0) {
259 Py_INCREF(method);
260 return (PyObject *)method;
261 }
262 }
263
264 return Nuitka_Method_New(method->m_function, object, class_object);
265}
266#endif
267
268static PyObject *Nuitka_Method_tp_getattro(struct Nuitka_MethodObject *method, PyObject *name) {
269 PyObject *descr = Nuitka_TypeLookup(&Nuitka_Method_Type, name);
270
271 if (descr != NULL) {
272 if (NuitkaType_HasFeatureClass(Py_TYPE(descr)) && (Py_TYPE(descr)->tp_descr_get != NULL)) {
273 return Py_TYPE(descr)->tp_descr_get(descr, (PyObject *)method, (PyObject *)Py_TYPE(method));
274 } else {
275 Py_INCREF(descr);
276 return descr;
277 }
278 }
279
280 // Delegate all other attributes to the underlying function.
281 // TODO: Could be a bit more direct here, and know this is generic lookup.
282 return PyObject_GetAttr((PyObject *)method->m_function, name);
283}
284
285static long Nuitka_Method_tp_traverse(struct Nuitka_MethodObject *method, visitproc visit, void *arg) {
286 Py_VISIT(method->m_function);
287 Py_VISIT(method->m_object);
288 Py_VISIT(method->m_class);
289
290 return 0;
291}
292
293// tp_repr slot, decide how a function shall be output
294static PyObject *Nuitka_Method_tp_repr(struct Nuitka_MethodObject *method) {
295 if (method->m_object == NULL) {
296#if PYTHON_VERSION < 0x300
297 return PyString_FromFormat("<unbound compiled_method %s.%s>", GET_CLASS_NAME(method->m_class),
298 Nuitka_String_AsString(method->m_function->m_name));
299#else
300 return PyUnicode_FromFormat("<compiled_function %s at %p>", Nuitka_String_AsString(method->m_function->m_name),
301 method->m_function);
302#endif
303 } else {
304 // Note: CPython uses repr of the object, although a comment despises
305 // it, we do it for compatibility.
306 PyObject *object_repr = PyObject_Repr(method->m_object);
307
308 if (object_repr == NULL) {
309 return NULL;
310 }
311#if PYTHON_VERSION < 0x300
312 else if (!PyString_Check(object_repr)) {
313 Py_DECREF(object_repr);
314 return NULL;
315 }
316#else
317 else if (!PyUnicode_Check(object_repr)) {
318 Py_DECREF(object_repr);
319 return NULL;
320 }
321#endif
322
323#if PYTHON_VERSION < 0x350
324 PyObject *result =
325 Nuitka_String_FromFormat("<bound compiled_method %s.%s of %s>", GET_CLASS_NAME(method->m_class),
326 Nuitka_String_AsString_Unchecked(method->m_function->m_name),
327 Nuitka_String_AsString_Unchecked(object_repr));
328#else
329 PyObject *result =
330 PyUnicode_FromFormat("<bound compiled_method %U of %U>", method->m_function->m_qualname, object_repr);
331#endif
332
333 Py_DECREF(object_repr);
334
335 return result;
336 }
337}
338
339#if PYTHON_VERSION < 0x300
340static int Nuitka_Method_tp_compare(struct Nuitka_MethodObject *a, struct Nuitka_MethodObject *b) {
341 if (a->m_function->m_counter < b->m_function->m_counter) {
342 return -1;
343 } else if (a->m_function->m_counter > b->m_function->m_counter) {
344 return 1;
345 } else if (a->m_object == b->m_object) {
346 return 0;
347 } else if (a->m_object == NULL) {
348 return -1;
349 } else if (b->m_object == NULL) {
350 return 1;
351 } else {
352 return PyObject_Compare(a->m_object, b->m_object);
353 }
354}
355#endif
356
357static PyObject *Nuitka_Method_tp_richcompare(struct Nuitka_MethodObject *a, struct Nuitka_MethodObject *b, int op) {
358 if (op != Py_EQ && op != Py_NE) {
359 Py_INCREF(Py_NotImplemented);
360 return Py_NotImplemented;
361 }
362
363 if (Nuitka_Method_Check((PyObject *)a) == false || Nuitka_Method_Check((PyObject *)b) == false) {
364 Py_INCREF(Py_NotImplemented);
365 return Py_NotImplemented;
366 }
367
368 bool b_res = a->m_function->m_counter == b->m_function->m_counter;
369
370 // If the underlying function objects are the same, check the objects, which
371 // may be NULL in case of unbound methods, which would be the same again.
372 if (b_res) {
373#if PYTHON_VERSION < 0x380
374 if (a->m_object == NULL) {
375 b_res = b->m_object == NULL;
376 } else if (b->m_object == NULL) {
377 b_res = false;
378 } else {
379 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(a->m_object, b->m_object);
380
381 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
382 return NULL;
383 }
384
385 b_res = nbool_res == NUITKA_BOOL_TRUE;
386 }
387#else
388 b_res = a->m_object == b->m_object;
389#endif
390 }
391
392 PyObject *result;
393
394 if (op == Py_EQ) {
395 result = BOOL_FROM(b_res);
396 } else {
397 result = BOOL_FROM(!b_res);
398 }
399
400 Py_INCREF_IMMORTAL(result);
401 return result;
402}
403
404static long Nuitka_Method_tp_hash(struct Nuitka_MethodObject *method) {
405 // Just give the hash of the method function, that ought to be good enough.
406 return method->m_function->m_counter;
407}
408
409// Freelist setup
410#define MAX_METHOD_FREE_LIST_COUNT 100
411static struct Nuitka_MethodObject *free_list_methods = NULL;
412static int free_list_methods_count = 0;
413
414static void Nuitka_Method_tp_dealloc(struct Nuitka_MethodObject *method) {
415#ifndef __NUITKA_NO_ASSERT__
416 // Save the current exception, if any, we must to not corrupt it.
417 PyThreadState *tstate = PyThreadState_GET();
418
419 struct Nuitka_ExceptionPreservationItem saved_exception_state1;
420 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
421 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
422#endif
423
424 Nuitka_GC_UnTrack(method);
425
426 if (method->m_weakrefs != NULL) {
427 PyObject_ClearWeakRefs((PyObject *)method);
428 }
429
430 Py_XDECREF(method->m_object);
431 Py_XDECREF(method->m_class);
432
433 Py_DECREF((PyObject *)method->m_function);
434
435 /* Put the object into free list or release to GC */
436 releaseToFreeList(free_list_methods, method, MAX_METHOD_FREE_LIST_COUNT);
437
438#ifndef __NUITKA_NO_ASSERT__
439 struct Nuitka_ExceptionPreservationItem saved_exception_state2;
440 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
441 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
442
443 ASSERT_SAME_EXCEPTION_STATE(&saved_exception_state1, &saved_exception_state2);
444#endif
445}
446
447static PyObject *Nuitka_Method_tp_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
448 PyObject *func;
449 PyObject *self;
450 PyObject *class_object = NULL;
451
452 if (!_PyArg_NoKeywords("compiled_method", kw)) {
453 return NULL;
454 }
455
456 if (!PyArg_UnpackTuple(args, "compiled_method", 2, 3, &func, &self, &class_object)) {
457 return NULL;
458 }
459
460 CHECK_OBJECT(func);
461
462 if (!PyCallable_Check(func)) {
463 PyThreadState *tstate = PyThreadState_GET();
464
465 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "first argument must be callable");
466 return NULL;
467 }
468
469 if (self == Py_None) {
470 self = NULL;
471 }
472
473 if (self == NULL && class_object == NULL) {
474 PyThreadState *tstate = PyThreadState_GET();
475
476 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "unbound methods must have non-NULL im_class");
477 return NULL;
478 }
479
480 if (Nuitka_Method_Check(func)) {
481 return Nuitka_Method_New(((struct Nuitka_MethodObject *)func)->m_function, self, class_object);
482 }
483
484 if (Nuitka_Function_Check(func) == false) {
485 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE("Cannot create compiled_ method from type '%s'", func);
486 return NULL;
487 }
488
489 return Nuitka_Method_New((struct Nuitka_FunctionObject *)func, self, class_object);
490}
491
492PyTypeObject Nuitka_Method_Type = {
493 PyVarObject_HEAD_INIT(NULL, 0) "compiled_method",
494 sizeof(struct Nuitka_MethodObject),
495 0,
496 (destructor)Nuitka_Method_tp_dealloc, // tp_dealloc
497#if PYTHON_VERSION < 0x380 || defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
498 0, // tp_print
499#else
500 offsetof(struct Nuitka_MethodObject, m_vectorcall), // tp_vectorcall_offset
501#endif
502 0, // tp_getattr
503 0, // tp_setattr
504#if PYTHON_VERSION < 0x300
505 (cmpfunc)Nuitka_Method_tp_compare, // tp_compare
506#else
507 0,
508#endif
509 (reprfunc)Nuitka_Method_tp_repr, // tp_repr
510 0, // tp_as_number
511 0, // tp_as_sequence
512 0, // tp_as_mapping
513 (hashfunc)Nuitka_Method_tp_hash, // tp_hash
514 (ternaryfunc)Nuitka_Method_tp_call, // tp_call
515 0, // tp_str
516 (getattrofunc)Nuitka_Method_tp_getattro, // tp_getattro
517 0, // tp_setattro (PyObject_GenericSetAttr)
518 0, // tp_as_buffer
519 Py_TPFLAGS_DEFAULT | // tp_flags
520#if PYTHON_VERSION < 0x300
521 Py_TPFLAGS_HAVE_WEAKREFS |
522#endif
523#if PYTHON_VERSION >= 0x380
524 _Py_TPFLAGS_HAVE_VECTORCALL |
525#endif
526 Py_TPFLAGS_HAVE_GC,
527 0, // tp_doc
528 (traverseproc)Nuitka_Method_tp_traverse, // tp_traverse
529 0, // tp_clear
530 (richcmpfunc)Nuitka_Method_tp_richcompare, // tp_richcompare
531 offsetof(struct Nuitka_MethodObject, m_weakrefs), // tp_weaklistoffset
532 0, // tp_iter
533 0, // tp_iternext
534 Nuitka_Method_methods, // tp_methods
535 Nuitka_Method_members, // tp_members
536 Nuitka_Method_tp_getset, // tp_getset
537 0, // tp_base
538 0, // tp_dict
539#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
540 (descrgetfunc)Nuitka_Method_tp_descr_get, // tp_descr_get
541#else
542 0,
543#endif
544 0, // tp_descr_set
545 0, // tp_dictoffset
546 0, // tp_init
547 0, // tp_alloc
548 Nuitka_Method_tp_new, // tp_new
549 0, // tp_free
550 0, // tp_is_gc
551 0, // tp_bases
552 0, // tp_mro
553 0, // tp_cache
554 0, // tp_subclasses
555 0, // tp_weaklist
556 0, // tp_del
557 0 // tp_version_tag
558#if PYTHON_VERSION >= 0x300
559 ,
560 0 /* tp_finalizer */
561#endif
562};
563
564void _initCompiledMethodType(void) {
565 Nuitka_PyType_Ready(&Nuitka_Method_Type, &PyMethod_Type, false, true, false, false, false);
566}
567
568PyObject *Nuitka_Method_New(struct Nuitka_FunctionObject *function, PyObject *object, PyObject *class_object) {
569 struct Nuitka_MethodObject *result;
570
571 CHECK_OBJECT((PyObject *)function);
572 assert(Nuitka_Function_Check((PyObject *)function));
573 assert(_PyObject_GC_IS_TRACKED(function));
574
575 allocateFromFreeListFixed(free_list_methods, struct Nuitka_MethodObject, Nuitka_Method_Type);
576
577 if (unlikely(result == NULL)) {
578 PyErr_Format(PyExc_RuntimeError, "cannot create method %s", Nuitka_String_AsString(function->m_name));
579
580 return NULL;
581 }
582
583 Py_INCREF(function);
584 result->m_function = function;
585
586 result->m_object = object;
587 Py_XINCREF(object);
588 result->m_class = class_object;
589 Py_XINCREF(class_object);
590
591 result->m_weakrefs = NULL;
592
593#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
594 result->m_vectorcall = (vectorcallfunc)Nuitka_Method_tp_vectorcall;
595#endif
596
597 Nuitka_GC_Track(result);
598 return (PyObject *)result;
599}
600
601// Part of "Nuitka", an optimizing Python compiler that is compatible and
602// integrates with CPython, but also works on its own.
603//
604// Licensed under the Apache License, Version 2.0 (the "License");
605// you may not use this file except in compliance with the License.
606// You may obtain a copy of the License at
607//
608// http://www.apache.org/licenses/LICENSE-2.0
609//
610// Unless required by applicable law or agreed to in writing, software
611// distributed under the License is distributed on an "AS IS" BASIS,
612// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
613// See the License for the specific language governing permissions and
614// limitations under the License.
Definition exceptions.h:712
Definition compiled_function.h:22
Definition compiled_method.h:16