@@ -202,7 +202,10 @@ def emit_line() -> None:
202
202
fields ['tp_basicsize' ] = base_size
203
203
204
204
if generate_full :
205
- emitter .emit_line ('static PyObject *{}(void);' .format (setup_name ))
205
+ # Declare setup method that allocates and initializes an object. type is the
206
+ # type of the class being initialized, which could be another class if there
207
+ # is an interpreted subclass.
208
+ emitter .emit_line ('static PyObject *{}(PyTypeObject *type);' .format (setup_name ))
206
209
assert cl .ctor is not None
207
210
emitter .emit_line (native_function_header (cl .ctor , emitter ) + ';' )
208
211
@@ -216,7 +219,15 @@ def emit_line() -> None:
216
219
generate_dealloc_for_class (cl , dealloc_name , clear_name , emitter )
217
220
emit_line ()
218
221
generate_native_getters_and_setters (cl , emitter )
219
- vtable_name = generate_vtables (cl , vtable_setup_name , vtable_name , emitter )
222
+
223
+ if cl .allow_interpreted_subclasses :
224
+ shadow_vtable_name = generate_vtables (
225
+ cl , vtable_setup_name + "_shadow" , vtable_name + "_shadow" , emitter , shadow = True
226
+ ) # type: Optional[str]
227
+ emit_line ()
228
+ else :
229
+ shadow_vtable_name = None
230
+ vtable_name = generate_vtables (cl , vtable_setup_name , vtable_name , emitter , shadow = False )
220
231
emit_line ()
221
232
if needs_getseters :
222
233
generate_getseter_declarations (cl , emitter )
@@ -241,7 +252,8 @@ def emit_line() -> None:
241
252
242
253
emitter .emit_line ()
243
254
if generate_full :
244
- generate_setup_for_class (cl , setup_name , defaults_fn , vtable_name , emitter )
255
+ generate_setup_for_class (
256
+ cl , setup_name , defaults_fn , vtable_name , shadow_vtable_name , emitter )
245
257
emitter .emit_line ()
246
258
generate_constructor_for_class (
247
259
cl , cl .ctor , init_fn , setup_name , vtable_name , emitter )
@@ -344,7 +356,8 @@ def generate_native_getters_and_setters(cl: ClassIR,
344
356
def generate_vtables (base : ClassIR ,
345
357
vtable_setup_name : str ,
346
358
vtable_name : str ,
347
- emitter : Emitter ) -> str :
359
+ emitter : Emitter ,
360
+ shadow : bool ) -> str :
348
361
"""Emit the vtables and vtable setup functions for a class.
349
362
350
363
This includes both the primary vtable and any trait implementation vtables.
@@ -354,13 +367,18 @@ def generate_vtables(base: ClassIR,
354
367
emit empty array definitions to store the vtables and a function to
355
368
populate them.
356
369
370
+ If shadow is True, generate "shadow vtables" that point to the
371
+ shadow glue methods (which should dispatch via the Python C-API).
372
+
357
373
Returns the expression to use to refer to the vtable, which might be
358
374
different than the name, if there are trait vtables.
375
+
359
376
"""
360
377
361
378
def trait_vtable_name (trait : ClassIR ) -> str :
362
- return '{}_{}_trait_vtable' .format (
363
- base .name_prefix (emitter .names ), trait .name_prefix (emitter .names ))
379
+ return '{}_{}_trait_vtable{}' .format (
380
+ base .name_prefix (emitter .names ), trait .name_prefix (emitter .names ),
381
+ '_shadow' if shadow else '' )
364
382
365
383
# Emit array definitions with enough space for all the entries
366
384
emitter .emit_line ('static CPyVTableItem {}[{}];' .format (
@@ -376,13 +394,16 @@ def trait_vtable_name(trait: ClassIR) -> str:
376
394
emitter .emit_line ('{}{}(void)' .format (NATIVE_PREFIX , vtable_setup_name ))
377
395
emitter .emit_line ('{' )
378
396
397
+ if base .allow_interpreted_subclasses and not shadow :
398
+ emitter .emit_line ('{}{}_shadow();' .format (NATIVE_PREFIX , vtable_setup_name ))
399
+
379
400
subtables = []
380
401
for trait , vtable in base .trait_vtables .items ():
381
402
name = trait_vtable_name (trait )
382
- generate_vtable (vtable , name , emitter , [])
403
+ generate_vtable (vtable , name , emitter , [], shadow )
383
404
subtables .append ((trait , name ))
384
405
385
- generate_vtable (base .vtable_entries , vtable_name , emitter , subtables )
406
+ generate_vtable (base .vtable_entries , vtable_name , emitter , subtables , shadow )
386
407
387
408
emitter .emit_line ('return 1;' )
388
409
emitter .emit_line ('}' )
@@ -393,7 +414,8 @@ def trait_vtable_name(trait: ClassIR) -> str:
393
414
def generate_vtable (entries : VTableEntries ,
394
415
vtable_name : str ,
395
416
emitter : Emitter ,
396
- subtables : List [Tuple [ClassIR , str ]]) -> None :
417
+ subtables : List [Tuple [ClassIR , str ]],
418
+ shadow : bool ) -> None :
397
419
emitter .emit_line ('CPyVTableItem {}_scratch[] = {{' .format (vtable_name ))
398
420
if subtables :
399
421
emitter .emit_line ('/* Array of trait vtables */' )
@@ -404,10 +426,11 @@ def generate_vtable(entries: VTableEntries,
404
426
405
427
for entry in entries :
406
428
if isinstance (entry , VTableMethod ):
429
+ method = entry .shadow_method if shadow and entry .shadow_method else entry .method
407
430
emitter .emit_line ('(CPyVTableItem){}{}{},' .format (
408
431
emitter .get_group_prefix (entry .method .decl ),
409
432
NATIVE_PREFIX ,
410
- entry . method .cname (emitter .names )))
433
+ method .cname (emitter .names )))
411
434
else :
412
435
cl , attr , is_setter = entry
413
436
namer = native_setter_name if is_setter else native_getter_name
@@ -425,18 +448,27 @@ def generate_setup_for_class(cl: ClassIR,
425
448
func_name : str ,
426
449
defaults_fn : Optional [FuncIR ],
427
450
vtable_name : str ,
451
+ shadow_vtable_name : Optional [str ],
428
452
emitter : Emitter ) -> None :
429
453
"""Generate a native function that allocates an instance of a class."""
430
454
emitter .emit_line ('static PyObject *' )
431
- emitter .emit_line ('{}(void )' .format (func_name ))
455
+ emitter .emit_line ('{}(PyTypeObject *type )' .format (func_name ))
432
456
emitter .emit_line ('{' )
433
457
emitter .emit_line ('{} *self;' .format (cl .struct_name (emitter .names )))
434
- emitter .emit_line ('self = ({struct} *){type_struct}->tp_alloc({type_struct}, 0);' .format (
435
- struct = cl .struct_name (emitter .names ),
436
- type_struct = emitter .type_struct_name (cl )))
458
+ emitter .emit_line ('self = ({struct} *)type->tp_alloc(type, 0);' .format (
459
+ struct = cl .struct_name (emitter .names )))
437
460
emitter .emit_line ('if (self == NULL)' )
438
461
emitter .emit_line (' return NULL;' )
439
- emitter .emit_line ('self->vtable = {};' .format (vtable_name ))
462
+
463
+ if shadow_vtable_name :
464
+ emitter .emit_line ('if (type != {}) {{' .format (emitter .type_struct_name (cl )))
465
+ emitter .emit_line ('self->vtable = {};' .format (shadow_vtable_name ))
466
+ emitter .emit_line ('} else {' )
467
+ emitter .emit_line ('self->vtable = {};' .format (vtable_name ))
468
+ emitter .emit_line ('}' )
469
+ else :
470
+ emitter .emit_line ('self->vtable = {};' .format (vtable_name ))
471
+
440
472
for base in reversed (cl .base_mro ):
441
473
for attr , rtype in base .attributes .items ():
442
474
emitter .emit_line ('self->{} = {};' .format (
@@ -464,7 +496,7 @@ def generate_constructor_for_class(cl: ClassIR,
464
496
"""Generate a native function that allocates and initializes an instance of a class."""
465
497
emitter .emit_line ('{}' .format (native_function_header (fn , emitter )))
466
498
emitter .emit_line ('{' )
467
- emitter .emit_line ('PyObject *self = {}();' .format (setup_name ))
499
+ emitter .emit_line ('PyObject *self = {}({} );' .format (setup_name , emitter . type_struct_name ( cl ) ))
468
500
emitter .emit_line ('if (self == NULL)' )
469
501
emitter .emit_line (' return NULL;' )
470
502
args = ', ' .join (['self' ] + [REG_PREFIX + arg .name for arg in fn .sig .args ])
@@ -525,13 +557,15 @@ def generate_new_for_class(cl: ClassIR,
525
557
'{}(PyTypeObject *type, PyObject *args, PyObject *kwds)' .format (func_name ))
526
558
emitter .emit_line ('{' )
527
559
# TODO: Check and unbox arguments
528
- emitter .emit_line ('if (type != {}) {{' .format (emitter .type_struct_name (cl )))
529
- emitter .emit_line (
530
- 'PyErr_SetString(PyExc_TypeError, "interpreted classes cannot inherit from compiled");' )
531
- emitter .emit_line ('return NULL;' )
532
- emitter .emit_line ('}' )
560
+ if not cl .allow_interpreted_subclasses :
561
+ emitter .emit_line ('if (type != {}) {{' .format (emitter .type_struct_name (cl )))
562
+ emitter .emit_line (
563
+ 'PyErr_SetString(PyExc_TypeError, "interpreted classes cannot inherit from compiled");'
564
+ )
565
+ emitter .emit_line ('return NULL;' )
566
+ emitter .emit_line ('}' )
533
567
534
- emitter .emit_line ('return {}();' .format (setup_name ))
568
+ emitter .emit_line ('return {}(type );' .format (setup_name ))
535
569
emitter .emit_line ('}' )
536
570
537
571
0 commit comments