@@ -162,375 +162,6 @@ Py_ssize_t PyObject_Size(PyObject *o) {
162
162
return UPCALL_CEXT_L ("PyObject_Size" , native_to_java (o ));
163
163
}
164
164
165
- static int add_subclass (PyTypeObject * base , PyTypeObject * type ) {
166
- void * key = PyLong_FromVoidPtr ((void * ) type );
167
- if (key == NULL ) {
168
- return -1 ;
169
- }
170
- if (polyglot_is_value (base )) {
171
- return polyglot_as_i32 (polyglot_invoke (PY_TRUFFLE_CEXT , "PyTruffle_Add_Subclass" , native_to_java ((PyObject * )base ), native_to_java (key ), native_to_java ((PyObject * )type )));
172
- } else {
173
- PyObject * dict = base -> tp_subclasses ;
174
- if (dict == NULL ) {
175
- base -> tp_subclasses = dict = PyDict_New ();
176
- if (dict == NULL ) {
177
- return -1 ;
178
- }
179
- }
180
- // TODO value should be a weak reference !
181
- return PyDict_SetItem (base -> tp_subclasses , key , (PyObject * )type );
182
- }
183
- return -1 ;
184
- }
185
-
186
- /* Special C landing functions that convert some arguments to primitives. */
187
-
188
- static PyObject * wrap_allocfunc (allocfunc f , PyTypeObject * klass , PyObject * n ) {
189
- return f (klass , PyLong_AsSsize_t (n ));
190
- }
191
-
192
- /* Wrapper around a native function to be called by Python code. */
193
- static PyObject * wrap_getattrfunc (getattrfunc f , PyObject * obj , PyObject * unicode ) {
194
- // we really need to provide 'char *' since this often runs non-Sulong code
195
- return f (obj , as_char_pointer (unicode ));
196
- }
197
-
198
- /* Wrapper around the native function to be called by Python code. */
199
- static PyObject * wrap_setattrfunc (setattrfunc f , PyObject * obj , PyObject * unicode , PyObject * value ) {
200
- // we really need to provide 'char *' since this often runs non-Sulong code
201
- return f (obj , as_char_pointer (unicode ), value );
202
- }
203
-
204
- static PyObject * wrap_setattrofunc (setattrofunc f , PyObject * obj , PyObject * key , PyObject * item ) {
205
- return PyLong_FromLong (f (obj , key , item ));
206
- }
207
-
208
- static PyObject * wrap_richcmpfunc (richcmpfunc f , PyObject * a , PyObject * b , PyObject * n ) {
209
- return f (a , b , (int )PyLong_AsLong (n ));
210
- }
211
-
212
- static PyObject * wrap_ssizeobjargproc (ssizeobjargproc f , PyObject * a , PyObject * size , PyObject * b ) {
213
- return PyLong_FromLong (f (a , PyLong_AsSsize_t (size ), b ));
214
- }
215
-
216
- static PyObject * wrap_ssizeargfunc (ssizeargfunc f , PyObject * a , PyObject * size ) {
217
- return PyLong_FromLong (f (a , PyLong_AsSsize_t (size )));
218
- }
219
-
220
- static PyObject * wrap_initproc (initproc f , PyObject * a , PyObject * b , PyObject * c ) {
221
- return PyLong_FromLong (f (a , b , c ));
222
- }
223
-
224
- static PyObject * wrap_objobjargproc (objobjargproc f , PyObject * a , PyObject * b , PyObject * c ) {
225
- return PyLong_FromLong (f (a , b , c ));
226
- }
227
-
228
- static PyObject * wrap_objobjproc (objobjproc f , PyObject * a , PyObject * b ) {
229
- return PyLong_FromLong (f (a , b ));
230
- }
231
-
232
- static PyObject * wrap_inquiry (inquiry f , PyObject * a ) {
233
- return PyLong_FromLong (f (a ));
234
- }
235
-
236
- /* very special case: operator '**' has an optional third arg */
237
- static PyObject * wrap_pow (ternaryfunc f , ...) {
238
- int nargs = polyglot_get_arg_count ();
239
- switch (nargs ) {
240
- case 3 :
241
- // TODO use 'native_to_java' on result
242
- return f (polyglot_get_arg (1 ), polyglot_get_arg (2 ), Py_None );
243
- case 4 :
244
- // TODO use 'native_to_java' on result
245
- return f (polyglot_get_arg (1 ), polyglot_get_arg (2 ), polyglot_get_arg (3 ));
246
- }
247
- return Py_NoValue ;
248
- }
249
-
250
- static PyObject * wrap_lenfunc (lenfunc f , PyObject * a ) {
251
- return PyLong_FromSsize_t (f (a ));
252
- }
253
-
254
- static Py_hash_t wrap_hashfunc (hashfunc f , PyObject * a ) {
255
- return PyLong_FromSsize_t (f (a ));
256
- }
257
-
258
- static PyObject * wrap_reverse_binop (binaryfunc f , PyObject * a , PyObject * b ) {
259
- return f (b , a );
260
- }
261
-
262
- int PyType_Ready (PyTypeObject * cls ) {
263
- #define ADD_IF_MISSING (attr , def ) if (!(attr)) { attr = def; }
264
- #define ADD_METHOD (m ) ADD_METHOD_OR_SLOT(m.ml_name, get_method_flags_cwrapper(m.ml_flags), m.ml_meth, m.ml_flags, m.ml_doc)
265
- #define ADD_SLOT (name , meth , flags ) ADD_METHOD_OR_SLOT(name, get_method_flags_cwrapper(flags), meth, flags, name)
266
- #define ADD_SLOT_CONV (name , clanding , meth , flags ) ADD_METHOD_OR_SLOT(name, clanding, meth, flags, name)
267
- #define ADD_METHOD_OR_SLOT (name , clanding , meth , flags , doc ) \
268
- if (meth) { \
269
- polyglot_invoke(PY_TRUFFLE_CEXT, \
270
- "AddFunction", \
271
- javacls, \
272
- polyglot_from_string((name), SRC_CS), \
273
- (meth), \
274
- (clanding), \
275
- get_method_flags_wrapper(flags), \
276
- polyglot_from_string(doc, SRC_CS), \
277
- (flags) > 0 && ((flags) & METH_CLASS) != 0, \
278
- (flags) > 0 && ((flags) & METH_STATIC) != 0); \
279
- }
280
-
281
- // https://docs.python.org/3/c-api/typeobj.html#Py_TPFLAGS_READY
282
- if ((cls -> tp_flags & Py_TPFLAGS_READY ) || (cls -> tp_flags & Py_TPFLAGS_READYING )) {
283
- return 0 ;
284
- }
285
- cls -> tp_flags = cls -> tp_flags | Py_TPFLAGS_READYING ;
286
-
287
- // https://docs.python.org/3/c-api/typeobj.html#c.PyObject.ob_type
288
- PyTypeObject * base = cls -> tp_base ;
289
- PyTypeObject * metaclass = Py_TYPE (cls );
290
- if (!base ) {
291
- base = & PyBaseObject_Type ;
292
- if (!metaclass ) {
293
- metaclass = & PyType_Type ;
294
- }
295
- } else {
296
- if (!metaclass ) {
297
- metaclass = Py_TYPE (base );
298
- }
299
- }
300
- cls -> tp_base = base ;
301
- Py_TYPE (cls ) = metaclass ;
302
-
303
- if (!(cls -> tp_doc )) {
304
- cls -> tp_doc = "" ;
305
- }
306
-
307
- /* Initialize tp_bases */
308
- PyObject * bases = cls -> tp_bases ;
309
- if (bases == NULL ) {
310
- if (base == NULL ) {
311
- bases = PyTuple_New (0 );
312
- } else {
313
- bases = PyTuple_Pack (1 , base );
314
- }
315
- if (bases == NULL ) {
316
- cls -> tp_flags &= ~Py_TPFLAGS_READYING ;
317
- return -1 ;
318
- }
319
- cls -> tp_bases = bases ;
320
- }
321
-
322
- PyObject * native_members = PyDict_New ();
323
- PyDict_SetItemString (native_members , "tp_name" , polyglot_from_string (cls -> tp_name , SRC_CS ));
324
- PyDict_SetItemString (native_members , "tp_doc" , polyglot_from_string (cls -> tp_doc ? cls -> tp_doc : "" , SRC_CS ));
325
- PyDict_SetItemString (native_members , "tp_basicsize" , PyLong_FromSsize_t (cls -> tp_basicsize ));
326
- const char * lastDot = strrchr (cls -> tp_name , '.' );
327
- if (lastDot ) {
328
- PyDict_SetItemString (native_members , "__module__" , polyglot_from_string (lastDot + 1 , SRC_CS ));
329
- }
330
- PyTypeObject * javacls = polyglot_invoke (PY_TRUFFLE_CEXT ,
331
- "PyType_Ready" ,
332
- // no conversion of cls here, because we
333
- // store this into the PyTypeObject
334
- cls ,
335
- native_to_java ((PyObject * )metaclass ),
336
- native_to_java (bases ),
337
- native_to_java (native_members ));
338
-
339
- // remember the managed wrapper
340
- ((PyObject * )cls )-> ob_refcnt = truffle_handle_for_managed (javacls );
341
- if (cls -> tp_dict != NULL ) {
342
- // TODO: (tfel) is this always safe?
343
- PyDict_Update (javacls -> tp_dict , cls -> tp_dict );
344
- }
345
- cls -> tp_dict = javacls -> tp_dict ;
346
-
347
- PyMethodDef * methods = cls -> tp_methods ;
348
- if (methods ) {
349
- int idx = 0 ;
350
- PyMethodDef def = methods [idx ];
351
- while (def .ml_name != NULL ) {
352
- if (!(def .ml_doc )) {
353
- def .ml_doc = "" ;
354
- }
355
- ADD_METHOD (def );
356
- def = methods [++ idx ];
357
- }
358
- }
359
-
360
- PyMemberDef * members = cls -> tp_members ;
361
- if (members ) {
362
- int i = 0 ;
363
- PyMemberDef member = members [i ];
364
- while (member .name != NULL ) {
365
- polyglot_invoke (PY_TRUFFLE_CEXT ,
366
- "AddMember" ,
367
- // TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between
368
- javacls ,
369
- polyglot_from_string (member .name , SRC_CS ),
370
- member .type ,
371
- member .offset ,
372
- // TODO: support other flags
373
- native_to_java (((member .flags & READONLY ) == 0 ) ? Py_True : Py_False ),
374
- polyglot_from_string (member .doc ? member .doc : "" , SRC_CS ));
375
- member = members [++ i ];
376
- }
377
- }
378
-
379
- PyGetSetDef * getsets = cls -> tp_getset ;
380
- if (getsets ) {
381
- int i = 0 ;
382
- PyGetSetDef getset = getsets [i ];
383
- while (getset .name != NULL ) {
384
- getter getter_fun = getset .get ;
385
- setter setter_fun = getset .set ;
386
- polyglot_invoke (PY_TRUFFLE_CEXT ,
387
- "AddGetSet" ,
388
- // TODO(fa): there should actually be 'native_to_java' just in case 'javacls' goes to native in between
389
- javacls ,
390
- polyglot_from_string (getset .name , SRC_CS ),
391
- getter_fun != NULL ? (getter )getter_fun : native_to_java (Py_None ),
392
- wrap_direct ,
393
- setter_fun != NULL ? (setter )setter_fun : native_to_java (Py_None ),
394
- wrap_setter ,
395
- getset .doc ? polyglot_from_string (getset .doc , SRC_CS ) : polyglot_from_string ("" , SRC_CS ),
396
- // do not convert the closure, it is handed to the
397
- // getter and setter as-is
398
- getset .closure );
399
- getset = getsets [++ i ];
400
- }
401
- }
402
-
403
- ADD_IF_MISSING (cls -> tp_alloc , PyType_GenericAlloc );
404
- ADD_IF_MISSING (cls -> tp_new , PyType_GenericNew );
405
-
406
- // add special methods defined directly on the type structs
407
- ADD_SLOT ("__dealloc__" , cls -> tp_dealloc , -1 );
408
- ADD_SLOT ("__print__" , cls -> tp_print , -3 );
409
- // https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_getattr
410
- // tp_getattr and tp_setattr are deprecated, and should be the same as
411
- // tp_getattro and tp_setattro
412
-
413
- // NOTE: The slots may be called from managed code, i.e., we need to wrap the functions
414
- // and convert arguments that should be C primitives.
415
- ADD_SLOT_CONV ("__getattr__" , wrap_getattrfunc , cls -> tp_getattr , -2 );
416
- ADD_SLOT_CONV ("__setattr__" , wrap_setattrfunc , cls -> tp_setattr , -3 );
417
- ADD_SLOT ("__repr__" , cls -> tp_repr , -1 );
418
- ADD_SLOT_CONV ("__hash__" , wrap_hashfunc , cls -> tp_hash , -1 );
419
- ADD_SLOT ("__call__" , cls -> tp_call , METH_KEYWORDS | METH_VARARGS );
420
- ADD_SLOT ("__str__" , cls -> tp_str , -1 );
421
- ADD_SLOT ("__getattr__" , cls -> tp_getattro , -2 );
422
- ADD_SLOT_CONV ("__setattr__" , wrap_setattrofunc , cls -> tp_setattro , -3 );
423
- ADD_SLOT ("__clear__" , cls -> tp_clear , -1 );
424
- ADD_SLOT_CONV ("__compare__" , wrap_richcmpfunc , cls -> tp_richcompare , -3 );
425
- ADD_SLOT ("__iter__" , cls -> tp_iter , -1 );
426
- ADD_SLOT ("__next__" , cls -> tp_iternext , -1 );
427
- ADD_SLOT ("__get__" , cls -> tp_descr_get , -3 );
428
- ADD_SLOT ("__set__" , cls -> tp_descr_set , -3 );
429
- ADD_SLOT_CONV ("__init__" , wrap_initproc , cls -> tp_init , METH_KEYWORDS | METH_VARARGS );
430
- ADD_SLOT_CONV ("__alloc__" , wrap_allocfunc , cls -> tp_alloc , -2 );
431
- ADD_SLOT ("__new__" , cls -> tp_new , METH_KEYWORDS | METH_VARARGS );
432
- ADD_SLOT ("__free__" , cls -> tp_free , -1 );
433
- ADD_SLOT ("__del__" , cls -> tp_del , -1 );
434
- ADD_SLOT ("__finalize__" , cls -> tp_finalize , -1 );
435
-
436
- PyNumberMethods * numbers = cls -> tp_as_number ;
437
- if (numbers ) {
438
- ADD_SLOT ("__add__" , numbers -> nb_add , -2 );
439
- ADD_SLOT_CONV ("__radd__" , wrap_reverse_binop , numbers -> nb_add , -2 );
440
- ADD_SLOT ("__sub__" , numbers -> nb_subtract , -2 );
441
- ADD_SLOT_CONV ("__rsub__" , wrap_reverse_binop , numbers -> nb_subtract , -2 );
442
- ADD_SLOT ("__mul__" , numbers -> nb_multiply , -2 );
443
- ADD_SLOT ("__rem__" , numbers -> nb_remainder , -2 );
444
- ADD_SLOT ("__divmod__" , numbers -> nb_divmod , -2 );
445
- ADD_SLOT_CONV ("__pow__" , wrap_pow , numbers -> nb_power , -3 );
446
- ADD_SLOT ("__neg__" , numbers -> nb_negative , -1 );
447
- ADD_SLOT ("__pos__" , numbers -> nb_positive , -1 );
448
- ADD_SLOT ("__abs__" , numbers -> nb_absolute , -1 );
449
- ADD_SLOT_CONV ("__bool__" , wrap_inquiry , numbers -> nb_bool , -1 );
450
- ADD_SLOT ("__invert__" , numbers -> nb_invert , -1 );
451
- ADD_SLOT ("__lshift__" , numbers -> nb_lshift , -2 );
452
- ADD_SLOT ("__rshift__" , numbers -> nb_rshift , -2 );
453
- ADD_SLOT ("__and__" , numbers -> nb_and , -2 );
454
- ADD_SLOT ("__xor__" , numbers -> nb_xor , -2 );
455
- ADD_SLOT ("__or__" , numbers -> nb_or , -2 );
456
- ADD_SLOT ("__int__" , numbers -> nb_int , -1 );
457
- ADD_SLOT ("__float__" , numbers -> nb_float , -1 );
458
- ADD_SLOT ("__iadd__" , numbers -> nb_inplace_add , -2 );
459
- ADD_SLOT ("__isub__" , numbers -> nb_inplace_subtract , -2 );
460
- ADD_SLOT ("__imul__" , numbers -> nb_inplace_multiply , -2 );
461
- ADD_SLOT ("__irem__" , numbers -> nb_inplace_remainder , -2 );
462
- ADD_SLOT ("__ipow__" , numbers -> nb_inplace_power , -2 );
463
- ADD_SLOT ("__ilshift__" , numbers -> nb_inplace_lshift , -2 );
464
- ADD_SLOT ("__irshift__" , numbers -> nb_inplace_rshift , -2 );
465
- ADD_SLOT ("__iand__" , numbers -> nb_inplace_and , -2 );
466
- ADD_SLOT ("__ixor__" , numbers -> nb_inplace_xor , -2 );
467
- ADD_SLOT ("__ior__" , numbers -> nb_inplace_or , -2 );
468
- ADD_SLOT ("__floordiv__" , numbers -> nb_floor_divide , -2 );
469
- ADD_SLOT ("__truediv__" , numbers -> nb_true_divide , -2 );
470
- ADD_SLOT ("__ifloordiv__" , numbers -> nb_inplace_floor_divide , -2 );
471
- ADD_SLOT ("__itruediv__" , numbers -> nb_inplace_true_divide , -2 );
472
- ADD_SLOT ("__index__" , numbers -> nb_index , -1 );
473
- ADD_SLOT ("__matmul__" , numbers -> nb_matrix_multiply , -2 );
474
- ADD_SLOT ("__imatmul__" , numbers -> nb_inplace_matrix_multiply , -2 );
475
- }
476
-
477
- PySequenceMethods * sequences = cls -> tp_as_sequence ;
478
- if (sequences ) {
479
- ADD_SLOT_CONV ("__len__" , wrap_lenfunc , sequences -> sq_length , -1 );
480
- ADD_SLOT ("__add__" , sequences -> sq_concat , -2 );
481
- ADD_SLOT_CONV ("__mul__" , wrap_ssizeargfunc , sequences -> sq_repeat , -2 );
482
- ADD_SLOT_CONV ("__getitem__" , wrap_ssizeargfunc , sequences -> sq_item , -2 );
483
- ADD_SLOT_CONV ("__setitem__" , wrap_ssizeobjargproc , sequences -> sq_ass_item , -3 );
484
- ADD_SLOT_CONV ("__contains__" , wrap_objobjproc , sequences -> sq_contains , -2 );
485
- ADD_SLOT ("__iadd__" , sequences -> sq_inplace_concat , -2 );
486
- ADD_SLOT_CONV ("__imul__" , wrap_ssizeargfunc , sequences -> sq_inplace_repeat , -2 );
487
- }
488
-
489
- PyMappingMethods * mappings = cls -> tp_as_mapping ;
490
- if (mappings ) {
491
- ADD_SLOT_CONV ("__len__" , wrap_lenfunc , mappings -> mp_length , -1 );
492
- ADD_SLOT ("__getitem__" , mappings -> mp_subscript , -2 );
493
- ADD_SLOT_CONV ("__setitem__" , wrap_objobjargproc , mappings -> mp_ass_subscript , -3 );
494
- }
495
-
496
- PyAsyncMethods * async = cls -> tp_as_async ;
497
- if (async ) {
498
- ADD_SLOT ("__await__" , async -> am_await , -1 );
499
- ADD_SLOT ("__aiter__" , async -> am_aiter , -1 );
500
- ADD_SLOT ("__anext__" , async -> am_anext , -1 );
501
- }
502
-
503
- PyBufferProcs * buffers = cls -> tp_as_buffer ;
504
- if (buffers ) {
505
- // TODO ...
506
- }
507
-
508
- /* Link into each base class's list of subclasses */
509
- bases = cls -> tp_bases ;
510
- Py_ssize_t n = PyTuple_GET_SIZE (bases );
511
- Py_ssize_t i ;
512
- for (i = 0 ; i < n ; i ++ ) {
513
- PyObject * base_class_object = PyTuple_GetItem (bases , i );
514
- PyTypeObject * b = (PyTypeObject * ) base_class_object ;
515
- if (PyType_Check (b ) && add_subclass (b , cls ) < 0 ) {
516
- cls -> tp_flags &= ~Py_TPFLAGS_READYING ;
517
- return -1 ;
518
- }
519
- }
520
-
521
- // done
522
- cls -> tp_flags = cls -> tp_flags & ~Py_TPFLAGS_READYING ;
523
- cls -> tp_flags = cls -> tp_flags | Py_TPFLAGS_READY ;
524
-
525
- return 0 ;
526
-
527
- #undef ADD_IF_MISSING
528
- #undef ADD_METHOD
529
- #undef ADD_SLOT
530
- #undef ADD_METHOD_OR_SLOT
531
- }
532
-
533
-
534
165
PyObject * PyObject_Str (PyObject * o ) {
535
166
return UPCALL_CEXT_O ("PyObject_Str" , native_to_java (o ));
536
167
}
0 commit comments