| 334 | |
| 335 | |
| 336 | def emit(stubs: list[ModuleStubs], output_path: Path) -> None: |
| 337 | method_table_id = 0 |
| 338 | out_lines: list[str] = [] |
| 339 | |
| 340 | for ms in stubs: |
| 341 | if not ms.classes and not ms.functions: |
| 342 | continue |
| 343 | out_lines.append(f"\n /* ===== module: {ms.module_qn} ===== */\n") |
| 344 | |
| 345 | for cls in ms.classes: |
| 346 | method_array_name = None |
| 347 | if cls.methods: |
| 348 | method_table_id += 1 |
| 349 | method_array_name = f"py_methods_{method_table_id}" |
| 350 | methods_c = ", ".join(f"\"{c_escape(m)}\"" for m in cls.methods) |
| 351 | out_lines.append( |
| 352 | f" static const char* {method_array_name}[] = {{ {methods_c}, NULL }};\n" |
| 353 | ) |
| 354 | out_lines.append(" memset(&rt, 0, sizeof(rt));\n") |
| 355 | out_lines.append( |
| 356 | f" rt.qualified_name = \"{c_escape(cls.qualified_name)}\";\n" |
| 357 | ) |
| 358 | out_lines.append( |
| 359 | f" rt.short_name = \"{c_escape(cls.short_name)}\";\n" |
| 360 | ) |
| 361 | if method_array_name: |
| 362 | out_lines.append(f" rt.method_names = {method_array_name};\n") |
| 363 | if cls.bases: |
| 364 | method_table_id += 1 |
| 365 | bases_array = f"py_bases_{method_table_id}" |
| 366 | bases_c = ", ".join(f"\"{c_escape(b)}\"" for b in cls.bases) |
| 367 | out_lines.append( |
| 368 | f" static const char* {bases_array}[] = {{ {bases_c}, NULL }};\n" |
| 369 | ) |
| 370 | out_lines.append(f" rt.embedded_types = {bases_array};\n") |
| 371 | out_lines.append(" cbm_registry_add_type(reg, rt);\n") |
| 372 | |
| 373 | # Also emit a registered method per class.method so registry |
| 374 | # lookup_method(class_qn, name) works. |
| 375 | for m in cls.methods: |
| 376 | out_lines.append(" memset(&rf, 0, sizeof(rf));\n") |
| 377 | out_lines.append( |
| 378 | f" rf.qualified_name = \"{c_escape(cls.qualified_name)}.{c_escape(m)}\";\n" |
| 379 | ) |
| 380 | out_lines.append(f" rf.short_name = \"{c_escape(m)}\";\n") |
| 381 | out_lines.append( |
| 382 | f" rf.receiver_type = \"{c_escape(cls.qualified_name)}\";\n" |
| 383 | ) |
| 384 | out_lines.append(" cbm_registry_add_func(reg, rf);\n") |
| 385 | |
| 386 | for fn in ms.functions: |
| 387 | out_lines.append(" memset(&rf, 0, sizeof(rf));\n") |
| 388 | out_lines.append( |
| 389 | f" rf.qualified_name = \"{c_escape(fn.qualified_name)}\";\n" |
| 390 | ) |
| 391 | out_lines.append(f" rf.short_name = \"{c_escape(fn.short_name)}\";\n") |
| 392 | out_lines.append(" cbm_registry_add_func(reg, rf);\n") |
| 393 | |