Generate C code for a class. This is the main entry point to the module.
(cl: ClassIR, module: str, emitter: Emitter)
| 236 | |
| 237 | |
| 238 | def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None: |
| 239 | """Generate C code for a class. |
| 240 | |
| 241 | This is the main entry point to the module. |
| 242 | """ |
| 243 | name = cl.name |
| 244 | name_prefix = cl.name_prefix(emitter.names) |
| 245 | |
| 246 | setup_name = emitter.native_function_name(cl.setup) |
| 247 | new_name = f"{name_prefix}_new" |
| 248 | finalize_name = f"{name_prefix}_finalize" |
| 249 | members_name = f"{name_prefix}_members" |
| 250 | getseters_name = f"{name_prefix}_getseters" |
| 251 | vtable_name = f"{name_prefix}_vtable" |
| 252 | traverse_name = f"{name_prefix}_traverse" |
| 253 | clear_name = f"{name_prefix}_clear" |
| 254 | dealloc_name = f"{name_prefix}_dealloc" |
| 255 | methods_name = f"{name_prefix}_methods" |
| 256 | vtable_setup_name = f"{name_prefix}_trait_vtable_setup" |
| 257 | coroutine_setup_name = f"{name_prefix}_coroutine_setup" |
| 258 | |
| 259 | fields: dict[str, str] = {"tp_name": f'"{name}"'} |
| 260 | |
| 261 | generate_full = not cl.is_trait and not cl.builtin_base |
| 262 | needs_getseters = cl.needs_getseters or not cl.is_generated or cl.has_dict |
| 263 | |
| 264 | if not cl.builtin_base: |
| 265 | fields["tp_new"] = new_name |
| 266 | |
| 267 | managed_dict = has_managed_dict(cl, emitter) |
| 268 | if generate_full or managed_dict: |
| 269 | fields["tp_dealloc"] = f"(destructor){name_prefix}_dealloc" |
| 270 | if not cl.is_acyclic: |
| 271 | fields["tp_traverse"] = f"(traverseproc){name_prefix}_traverse" |
| 272 | fields["tp_clear"] = f"(inquiry){name_prefix}_clear" |
| 273 | # Populate .tp_finalize and generate a finalize method only if __del__ is defined for this class. |
| 274 | del_method = next((e.method for e in cl.vtable_entries if e.name == "__del__"), None) |
| 275 | if del_method: |
| 276 | fields["tp_finalize"] = f"(destructor){finalize_name}" |
| 277 | if needs_getseters: |
| 278 | fields["tp_getset"] = getseters_name |
| 279 | fields["tp_methods"] = methods_name |
| 280 | |
| 281 | def emit_line() -> None: |
| 282 | emitter.emit_line() |
| 283 | |
| 284 | emit_line() |
| 285 | |
| 286 | # If the class has a method to initialize default attribute |
| 287 | # values, we need to call it during initialization. |
| 288 | defaults_fn = cl.get_method("__mypyc_defaults_setup") |
| 289 | |
| 290 | # If there is a __init__ method, we'll use it in the native constructor. |
| 291 | init_fn = cl.get_method("__init__") |
| 292 | |
| 293 | # Fill out slots in the type object from dunder methods. |
| 294 | fields.update(generate_slots(cl, SLOT_DEFS, emitter)) |
| 295 |
no test coverage detected
searching dependent graphs…