@@ -26,12 +26,14 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None:
2626 getseters_name = '{}_getseters' .format (name )
2727 methods_name = '{}_methods' .format (name )
2828 vtable_name = '{}_vtable' .format (name )
29+ base_arg = "&{}" .format (type_struct_name (cl .base .name )) if cl .base else "0"
2930
3031 def emit_line () -> None :
3132 emitter .emit_line ()
3233
3334 emit_line ()
3435 generate_object_struct (cl , emitter )
36+ emit_line ()
3537
3638 # If there is a __init__ method, generate a function for tp_init and
3739 # extract the args (which we'll use for the native constructor)
@@ -100,7 +102,7 @@ def emit_line() -> None:
100102 {methods_name}, /* tp_methods */
101103 0, /* tp_members */
102104 {getseters_name}, /* tp_getset */
103- 0, /* tp_base */
105+ {base_arg}, /* tp_base */
104106 0, /* tp_dict */
105107 0, /* tp_descr_get */
106108 0, /* tp_descr_set */
@@ -119,6 +121,7 @@ def emit_line() -> None:
119121 methods_name = methods_name ,
120122 getseters_name = getseters_name ,
121123 init_name = init_name ,
124+ base_arg = base_arg ,
122125 ))
123126 emitter .emit_line ()
124127 generate_setup_for_class (cl , setup_name , vtable_name , emitter )
@@ -148,14 +151,15 @@ def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None:
148151 emitter .emit_lines ('typedef struct {' ,
149152 'PyObject_HEAD' ,
150153 'CPyVTableItem *vtable;' )
151- for attr , rtype in cl .attributes :
152- emitter .emit_line ('{}{};' .format (rtype .ctype_spaced (), attr ))
154+ for base in reversed (cl .mro ):
155+ for attr , rtype in base .attributes .items ():
156+ emitter .emit_line ('{}{};' .format (rtype .ctype_spaced (), attr ))
153157 emitter .emit_line ('}} {};' .format (cl .struct_name ()))
154158
155159
156160def generate_native_getters_and_setters (cl : ClassIR ,
157161 emitter : Emitter ) -> None :
158- for attr , rtype in cl .attributes :
162+ for attr , rtype in cl .attributes . items () :
159163 # Native getter
160164 emitter .emit_line ('{}{}({} *self)' .format (rtype .ctype_spaced (),
161165 native_getter_name (cl .name , attr ),
@@ -189,15 +193,23 @@ def generate_native_getters_and_setters(cl: ClassIR,
189193 emitter .emit_line ()
190194
191195
192- def generate_vtable (cl : ClassIR ,
196+ def generate_vtable (base : ClassIR ,
193197 vtable_name : str ,
194198 emitter : Emitter ) -> None :
195199 emitter .emit_line ('static CPyVTableItem {}[] = {{' .format (vtable_name ))
196- for attr , rtype in cl .attributes :
197- emitter .emit_line ('(CPyVTableItem){},' .format (native_getter_name (cl .name , attr )))
198- emitter .emit_line ('(CPyVTableItem){},' .format (native_setter_name (cl .name , attr )))
199- for fn in cl .methods :
200- emitter .emit_line ('(CPyVTableItem){}{},' .format (NATIVE_PREFIX , fn .cname ))
200+ for cl in reversed (base .mro ):
201+ for attr in cl .attributes :
202+ emitter .emit_line ('(CPyVTableItem){},' .format (native_getter_name (cl .name , attr )))
203+ emitter .emit_line ('(CPyVTableItem){},' .format (native_setter_name (cl .name , attr )))
204+ for fn in cl .methods :
205+ # TODO: This is gross, and inefficient, and wrong if the type changes.
206+ # This logic should all live on the genops side, I think
207+ search = base .mro if fn .name != '__init__' else [cl ]
208+ for cl2 in search :
209+ m = cl2 .get_method (fn .name )
210+ if m :
211+ emitter .emit_line ('(CPyVTableItem){}{},' .format (NATIVE_PREFIX , m .cname ))
212+ break
201213 emitter .emit_line ('};' )
202214
203215
@@ -216,7 +228,7 @@ def generate_setup_for_class(cl: ClassIR,
216228 emitter .emit_line ('if (self == NULL)' )
217229 emitter .emit_line (' return NULL;' )
218230 emitter .emit_line ('self->vtable = {};' .format (vtable_name ))
219- for attr , rtype in cl .attributes :
231+ for attr , rtype in cl .attributes . items () :
220232 emitter .emit_line ('self->{} = {};' .format (attr , rtype .c_undefined_value ()))
221233 emitter .emit_line ('return (PyObject *)self;' )
222234 emitter .emit_line ('}' )
@@ -282,7 +294,7 @@ def generate_traverse_for_class(cl: ClassIR,
282294 emitter .emit_line ('{}({} *self, visitproc visit, void *arg)' .format (func_name ,
283295 cl .struct_name ()))
284296 emitter .emit_line ('{' )
285- for attr , rtype in cl .attributes :
297+ for attr , rtype in cl .attributes . items () :
286298 emitter .emit_gc_visit ('self->{}' .format (attr ), rtype )
287299 emitter .emit_line ('return 0;' )
288300 emitter .emit_line ('}' )
@@ -294,7 +306,7 @@ def generate_clear_for_class(cl: ClassIR,
294306 emitter .emit_line ('static int' )
295307 emitter .emit_line ('{}({} *self)' .format (func_name , cl .struct_name ()))
296308 emitter .emit_line ('{' )
297- for attr , rtype in cl .attributes :
309+ for attr , rtype in cl .attributes . items () :
298310 emitter .emit_gc_clear ('self->{}' .format (attr ), rtype )
299311 emitter .emit_line ('return 0;' )
300312 emitter .emit_line ('}' )
@@ -327,7 +339,7 @@ def generate_methods_table(cl: ClassIR,
327339
328340
329341def generate_getseter_declarations (cl : ClassIR , emitter : Emitter ) -> None :
330- for attr , rtype in cl .attributes :
342+ for attr in cl .attributes :
331343 emitter .emit_line ('static PyObject *' )
332344 emitter .emit_line ('{}({} *self, void *closure);' .format (getter_name (cl .name , attr ),
333345 cl .struct_name ()))
@@ -342,7 +354,7 @@ def generate_getseters_table(cl: ClassIR,
342354 emitter : Emitter ) -> None :
343355
344356 emitter .emit_line ('static PyGetSetDef {}[] = {{' .format (name ))
345- for attr , rtype in cl .attributes :
357+ for attr in cl .attributes :
346358 emitter .emit_line ('{{"{}",' .format (attr ))
347359 emitter .emit_line (' (getter){}, (setter){},' .format (getter_name (cl .name , attr ),
348360 setter_name (cl .name , attr )))
@@ -352,7 +364,7 @@ def generate_getseters_table(cl: ClassIR,
352364
353365
354366def generate_getseters (cl : ClassIR , emitter : Emitter ) -> None :
355- for i , (attr , rtype ) in enumerate (cl .attributes ):
367+ for i , (attr , rtype ) in enumerate (cl .attributes . items () ):
356368 generate_getter (cl , attr , rtype , emitter )
357369 emitter .emit_line ('' )
358370 generate_setter (cl , attr , rtype , emitter )
0 commit comments