1# coding=utf-8 2# 3# Copyright (c) 2025 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from json import dumps 17 18from taihe.codegen.abi.analyses import ( 19 EnumABIInfo, 20 IfaceABIInfo, 21 IfaceMethodABIInfo, 22 StructABIInfo, 23 TypeABIInfo, 24 UnionABIInfo, 25) 26from taihe.codegen.abi.writer import CHeaderWriter 27from taihe.codegen.cpp.analyses import ( 28 EnumCppInfo, 29 IfaceCppInfo, 30 IfaceMethodCppInfo, 31 PackageCppInfo, 32 StructCppInfo, 33 TypeCppInfo, 34 UnionCppInfo, 35) 36from taihe.semantics.declarations import ( 37 EnumDecl, 38 IfaceDecl, 39 PackageDecl, 40 PackageGroup, 41 StructDecl, 42 UnionDecl, 43) 44from taihe.semantics.types import ( 45 ScalarType, 46 StringType, 47) 48from taihe.utils.analyses import AnalysisManager 49from taihe.utils.outputs import FileKind, OutputManager 50 51 52class CppHeadersGenerator: 53 def __init__(self, om: OutputManager, am: AnalysisManager): 54 self.om = om 55 self.am = am 56 57 def generate(self, pg: PackageGroup): 58 for pkg in pg.packages: 59 self.gen_package_files(pkg) 60 61 def gen_package_files(self, pkg: PackageDecl): 62 pkg_cpp_info = PackageCppInfo.get(self.am, pkg) 63 with CHeaderWriter( 64 self.om, 65 f"include/{pkg_cpp_info.header}", 66 FileKind.CPP_HEADER, 67 ) as pkg_cpp_target: 68 for enum in pkg.enums: 69 enum_abi_info = EnumABIInfo.get(self.am, enum) 70 enum_cpp_info = EnumCppInfo.get(self.am, enum) 71 self.gen_enum_decl_file(enum, enum_abi_info, enum_cpp_info) 72 self.gen_enum_defn_file(enum, enum_abi_info, enum_cpp_info) 73 pkg_cpp_target.add_include(enum_cpp_info.defn_header) 74 for struct in pkg.structs: 75 struct_abi_info = StructABIInfo.get(self.am, struct) 76 struct_cpp_info = StructCppInfo.get(self.am, struct) 77 self.gen_struct_decl_file(struct, struct_abi_info, struct_cpp_info) 78 self.gen_struct_defn_file(struct, struct_abi_info, struct_cpp_info) 79 self.gen_struct_impl_file(struct, struct_abi_info, struct_cpp_info) 80 pkg_cpp_target.add_include(struct_cpp_info.impl_header) 81 for union in pkg.unions: 82 union_abi_info = UnionABIInfo.get(self.am, union) 83 union_cpp_info = UnionCppInfo.get(self.am, union) 84 self.gen_union_decl_file(union, union_abi_info, union_cpp_info) 85 self.gen_union_defn_file(union, union_abi_info, union_cpp_info) 86 self.gen_union_impl_file(union, union_abi_info, union_cpp_info) 87 pkg_cpp_target.add_include(union_cpp_info.impl_header) 88 for iface in pkg.interfaces: 89 iface_abi_info = IfaceABIInfo.get(self.am, iface) 90 iface_cpp_info = IfaceCppInfo.get(self.am, iface) 91 self.gen_iface_decl_file(iface, iface_abi_info, iface_cpp_info) 92 self.gen_iface_defn_file(iface, iface_abi_info, iface_cpp_info) 93 self.gen_iface_impl_file(iface, iface_abi_info, iface_cpp_info) 94 pkg_cpp_target.add_include(iface_cpp_info.impl_header) 95 96 def gen_enum_decl_file( 97 self, 98 enum: EnumDecl, 99 enum_abi_info: EnumABIInfo, 100 enum_cpp_info: EnumCppInfo, 101 ): 102 with CHeaderWriter( 103 self.om, 104 f"include/{enum_cpp_info.decl_header}", 105 FileKind.C_HEADER, 106 ) as enum_cpp_decl_target: 107 enum_cpp_decl_target.add_include("taihe/common.hpp") 108 with enum_cpp_decl_target.indented( 109 f"namespace {enum_cpp_info.namespace} {{", 110 f"}}", 111 indent="", 112 ): 113 enum_cpp_decl_target.writelns( 114 f"struct {enum_cpp_info.name};", 115 ) 116 with enum_cpp_decl_target.indented( 117 f"namespace taihe {{", 118 f"}}", 119 indent="", 120 ): 121 enum_cpp_decl_target.writelns( 122 f"template<>", 123 ) 124 with enum_cpp_decl_target.indented( 125 f"struct as_abi<{enum_cpp_info.full_name}> {{", 126 f"}};", 127 ): 128 enum_cpp_decl_target.writelns( 129 f"using type = {enum_abi_info.abi_type};", 130 ) 131 enum_cpp_decl_target.writelns( 132 f"template<>", 133 ) 134 with enum_cpp_decl_target.indented( 135 f"struct as_param<{enum_cpp_info.full_name}> {{", 136 f"}};", 137 ): 138 enum_cpp_decl_target.writelns( 139 f"using type = {enum_cpp_info.full_name};", 140 ) 141 142 def gen_enum_defn_file( 143 self, 144 enum: EnumDecl, 145 enum_abi_info: EnumABIInfo, 146 enum_cpp_info: EnumCppInfo, 147 ): 148 with CHeaderWriter( 149 self.om, 150 f"include/{enum_cpp_info.defn_header}", 151 FileKind.C_HEADER, 152 ) as enum_cpp_defn_target: 153 enum_cpp_defn_target.add_include(enum_cpp_info.decl_header) 154 self.gen_enum_defn( 155 enum, 156 enum_abi_info, 157 enum_cpp_info, 158 enum_cpp_defn_target, 159 ) 160 self.gen_enum_same( 161 enum, 162 enum_abi_info, 163 enum_cpp_info, 164 enum_cpp_defn_target, 165 ) 166 self.gen_enum_hash( 167 enum, 168 enum_abi_info, 169 enum_cpp_info, 170 enum_cpp_defn_target, 171 ) 172 173 def gen_enum_defn( 174 self, 175 enum: EnumDecl, 176 enum_abi_info: EnumABIInfo, 177 enum_cpp_info: EnumCppInfo, 178 enum_cpp_defn_target: CHeaderWriter, 179 ): 180 with enum_cpp_defn_target.indented( 181 f"namespace {enum_cpp_info.namespace} {{", 182 f"}}", 183 indent="", 184 ): 185 ty_cpp_info = TypeCppInfo.get(self.am, enum.ty_ref.resolved_ty) 186 enum_cpp_defn_target.add_include(*ty_cpp_info.impl_headers) 187 with enum_cpp_defn_target.indented( 188 f"struct {enum_cpp_info.name} {{", 189 f"}};", 190 ): 191 enum_cpp_defn_target.writelns( 192 f"public:", 193 ) 194 self.gen_enum_key_type( 195 enum, 196 enum_abi_info, 197 enum_cpp_info, 198 enum_cpp_defn_target, 199 ) 200 self.gen_enum_basic_methods( 201 enum, 202 enum_abi_info, 203 enum_cpp_info, 204 enum_cpp_defn_target, 205 ) 206 self.gen_enum_key_utils( 207 enum, 208 enum_abi_info, 209 enum_cpp_info, 210 enum_cpp_defn_target, 211 ) 212 self.gen_enum_value_utils( 213 enum, 214 enum_abi_info, 215 enum_cpp_info, 216 enum_cpp_defn_target, 217 ) 218 enum_cpp_defn_target.writelns( 219 f"private:", 220 ) 221 self.gen_enum_properties( 222 enum, 223 enum_abi_info, 224 enum_cpp_info, 225 enum_cpp_defn_target, 226 ) 227 228 def gen_enum_key_type( 229 self, 230 enum: EnumDecl, 231 enum_abi_info: EnumABIInfo, 232 enum_cpp_info: EnumCppInfo, 233 enum_cpp_defn_target: CHeaderWriter, 234 ): 235 with enum_cpp_defn_target.indented( 236 f"enum class key_t: {enum_abi_info.abi_type} {{", 237 f"}};", 238 ): 239 for item in enum.items: 240 enum_cpp_defn_target.writelns( 241 f"{item.name},", 242 ) 243 244 def gen_enum_properties( 245 self, 246 enum: EnumDecl, 247 enum_abi_info: EnumABIInfo, 248 enum_cpp_info: EnumCppInfo, 249 enum_cpp_defn_target: CHeaderWriter, 250 ): 251 enum_cpp_defn_target.writelns( 252 f"key_t key;", 253 ) 254 255 def gen_enum_basic_methods( 256 self, 257 enum: EnumDecl, 258 enum_abi_info: EnumABIInfo, 259 enum_cpp_info: EnumCppInfo, 260 enum_cpp_defn_target: CHeaderWriter, 261 ): 262 # copy constructor 263 enum_cpp_defn_target.writelns( 264 f"{enum_cpp_info.name}({enum_cpp_info.name} const& other) : key(other.key) {{}}", 265 ) 266 # copy assignment 267 with enum_cpp_defn_target.indented( 268 f"{enum_cpp_info.name}& operator=({enum_cpp_info.name} other) {{", 269 f"}}", 270 ): 271 enum_cpp_defn_target.writelns( 272 f"key = other.key;", 273 f"return *this;", 274 ) 275 276 def gen_enum_key_utils( 277 self, 278 enum: EnumDecl, 279 enum_abi_info: EnumABIInfo, 280 enum_cpp_info: EnumCppInfo, 281 enum_cpp_defn_target: CHeaderWriter, 282 ): 283 # constructor 284 enum_cpp_defn_target.writelns( 285 f"{enum_cpp_info.name}(key_t key) : key(key) {{}}", 286 ) 287 # key getter 288 with enum_cpp_defn_target.indented( 289 f"key_t get_key() const {{", 290 f"}}", 291 ): 292 enum_cpp_defn_target.writelns( 293 f"return this->key;", 294 ) 295 # validity checker 296 with enum_cpp_defn_target.indented( 297 f"bool is_valid() const {{", 298 f"}}", 299 ): 300 enum_cpp_defn_target.writelns( 301 f"return ({enum_abi_info.abi_type})key >= 0 && ({enum_abi_info.abi_type})key < {len(enum.items)};", 302 ) 303 304 def gen_enum_value_utils( 305 self, 306 enum: EnumDecl, 307 enum_abi_info: EnumABIInfo, 308 enum_cpp_info: EnumCppInfo, 309 enum_cpp_defn_target: CHeaderWriter, 310 ): 311 ty_cpp_info = TypeCppInfo.get(self.am, enum.ty_ref.resolved_ty) 312 match enum.ty_ref.resolved_ty: 313 case StringType(): 314 as_owner = "char const*" 315 as_param = ty_cpp_info.as_param 316 case ScalarType(): 317 as_owner = ty_cpp_info.as_owner 318 as_param = ty_cpp_info.as_param 319 case _: 320 raise ValueError("invalid enum type") 321 # table 322 with enum_cpp_defn_target.indented( 323 f"static constexpr {as_owner} table[] = {{", 324 f"}};", 325 ): 326 for item in enum.items: 327 enum_cpp_defn_target.writelns( 328 f"{dumps(item.value)},", 329 ) 330 # value getter 331 with enum_cpp_defn_target.indented( 332 f"{as_owner} get_value() const {{", 333 f"}}", 334 ): 335 enum_cpp_defn_target.writelns( 336 f"return table[({enum_abi_info.abi_type})key];", 337 ) 338 # value converter 339 with enum_cpp_defn_target.indented( 340 f"operator {as_owner}() const {{", 341 f"}}", 342 ): 343 enum_cpp_defn_target.writelns( 344 f"return table[({enum_abi_info.abi_type})key];", 345 ) 346 # creator from value 347 with enum_cpp_defn_target.indented( 348 f"static {enum_cpp_info.as_owner} from_value({as_param} value) {{", 349 f"}}", 350 ): 351 for i, item in enumerate(enum.items): 352 with enum_cpp_defn_target.indented( 353 f"if (value == {dumps(item.value)}) {{", 354 f"}}", 355 ): 356 enum_cpp_defn_target.writelns( 357 f"return {enum_cpp_info.as_owner}((key_t){i});", 358 ) 359 enum_cpp_defn_target.writelns( 360 f"return {enum_cpp_info.as_owner}((key_t)-1);", 361 ) 362 363 def gen_enum_same( 364 self, 365 enum: EnumDecl, 366 enum_abi_info: EnumABIInfo, 367 enum_cpp_info: EnumCppInfo, 368 enum_cpp_defn_target: CHeaderWriter, 369 ): 370 # others 371 with enum_cpp_defn_target.indented( 372 f"namespace {enum_cpp_info.namespace} {{", 373 f"}}", 374 indent="", 375 ): 376 with enum_cpp_defn_target.indented( 377 f"inline bool operator==({enum_cpp_info.as_param} lhs, {enum_cpp_info.as_param} rhs) {{", 378 f"}}", 379 ): 380 enum_cpp_defn_target.writelns( 381 f"return lhs.get_key() == rhs.get_key();", 382 ) 383 384 def gen_enum_hash( 385 self, 386 enum: EnumDecl, 387 enum_abi_info: EnumABIInfo, 388 enum_cpp_info: EnumCppInfo, 389 enum_cpp_defn_target: CHeaderWriter, 390 ): 391 with enum_cpp_defn_target.indented( 392 f"template<> struct ::std::hash<{enum_cpp_info.full_name}> {{", 393 f"}};", 394 ): 395 with enum_cpp_defn_target.indented( 396 f"size_t operator()({enum_cpp_info.as_param} val) const {{", 397 f"}}", 398 ): 399 enum_cpp_defn_target.writelns( 400 f"return ::std::hash<{enum_abi_info.abi_type}>()(({enum_abi_info.abi_type})val.get_key());", 401 ) 402 403 def gen_union_decl_file( 404 self, 405 union: UnionDecl, 406 union_abi_info: UnionABIInfo, 407 union_cpp_info: UnionCppInfo, 408 ): 409 with CHeaderWriter( 410 self.om, 411 f"include/{union_cpp_info.decl_header}", 412 FileKind.C_HEADER, 413 ) as union_cpp_decl_target: 414 union_cpp_decl_target.add_include("taihe/common.hpp") 415 union_cpp_decl_target.add_include(union_abi_info.decl_header) 416 with union_cpp_decl_target.indented( 417 f"namespace {union_cpp_info.namespace} {{", 418 f"}}", 419 indent="", 420 ): 421 union_cpp_decl_target.writelns( 422 f"struct {union_cpp_info.name};", 423 ) 424 with union_cpp_decl_target.indented( 425 f"namespace taihe {{", 426 f"}}", 427 indent="", 428 ): 429 union_cpp_decl_target.writelns( 430 f"template<>", 431 ) 432 with union_cpp_decl_target.indented( 433 f"struct as_abi<{union_cpp_info.as_owner}> {{", 434 f"}};", 435 ): 436 union_cpp_decl_target.writelns( 437 f"using type = {union_abi_info.as_owner};", 438 ) 439 union_cpp_decl_target.writelns( 440 f"template<>", 441 ) 442 with union_cpp_decl_target.indented( 443 f"struct as_abi<{union_cpp_info.as_param}> {{", 444 f"}};", 445 ): 446 union_cpp_decl_target.writelns( 447 f"using type = {union_abi_info.as_param};", 448 ) 449 union_cpp_decl_target.writelns( 450 f"template<>", 451 ) 452 with union_cpp_decl_target.indented( 453 f"struct as_param<{union_cpp_info.as_owner}> {{", 454 f"}};", 455 ): 456 union_cpp_decl_target.writelns( 457 f"using type = {union_cpp_info.as_param};", 458 ) 459 460 def gen_union_defn_file( 461 self, 462 union: UnionDecl, 463 union_abi_info: UnionABIInfo, 464 union_cpp_info: UnionCppInfo, 465 ): 466 with CHeaderWriter( 467 self.om, 468 f"include/{union_cpp_info.defn_header}", 469 FileKind.CPP_HEADER, 470 ) as union_cpp_defn_target: 471 union_cpp_defn_target.add_include(union_cpp_info.decl_header) 472 union_cpp_defn_target.add_include(union_abi_info.defn_header) 473 for field in union.fields: 474 if field.ty_ref is None: 475 continue 476 type_cpp_info = TypeCppInfo.get(self.am, field.ty_ref.resolved_ty) 477 union_cpp_defn_target.add_include(*type_cpp_info.defn_headers) 478 self.gen_union_defn( 479 union, 480 union_abi_info, 481 union_cpp_info, 482 union_cpp_defn_target, 483 ) 484 self.gen_union_same( 485 union, 486 union_abi_info, 487 union_cpp_info, 488 union_cpp_defn_target, 489 ) 490 self.gen_union_hash( 491 union, 492 union_abi_info, 493 union_cpp_info, 494 union_cpp_defn_target, 495 ) 496 497 def gen_union_defn( 498 self, 499 union: UnionDecl, 500 union_abi_info: UnionABIInfo, 501 union_cpp_info: UnionCppInfo, 502 union_cpp_defn_target: CHeaderWriter, 503 ): 504 with union_cpp_defn_target.indented( 505 f"namespace {union_cpp_info.namespace} {{", 506 f"}}", 507 indent="", 508 ): 509 with union_cpp_defn_target.indented( 510 f"struct {union_cpp_info.name} {{", 511 f"}};", 512 ): 513 union_cpp_defn_target.writelns( 514 f"public:", 515 ) 516 self.gen_union_tag_type( 517 union, 518 union_abi_info, 519 union_cpp_info, 520 union_cpp_defn_target, 521 ) 522 self.gen_union_storage_type( 523 union, 524 union_abi_info, 525 union_cpp_info, 526 union_cpp_defn_target, 527 ) 528 self.gen_union_basic_methods( 529 union, 530 union_abi_info, 531 union_cpp_info, 532 union_cpp_defn_target, 533 ) 534 self.gen_union_utils( 535 union, 536 union_abi_info, 537 union_cpp_info, 538 union_cpp_defn_target, 539 ) 540 self.gen_union_named_utils( 541 union, 542 union_abi_info, 543 union_cpp_info, 544 union_cpp_defn_target, 545 ) 546 union_cpp_defn_target.writelns( 547 f"private:", 548 ) 549 self.gen_union_properties( 550 union, 551 union_abi_info, 552 union_cpp_info, 553 union_cpp_defn_target, 554 ) 555 556 def gen_union_tag_type( 557 self, 558 union: UnionDecl, 559 union_abi_info: UnionABIInfo, 560 union_cpp_info: UnionCppInfo, 561 union_cpp_defn_target: CHeaderWriter, 562 ): 563 with union_cpp_defn_target.indented( 564 f"enum class tag_t : {union_abi_info.tag_type} {{", 565 f"}};", 566 ): 567 for field in union.fields: 568 union_cpp_defn_target.writelns( 569 f"{field.name},", 570 ) 571 572 def gen_union_storage_type( 573 self, 574 union: UnionDecl, 575 union_abi_info: UnionABIInfo, 576 union_cpp_info: UnionCppInfo, 577 union_cpp_defn_target: CHeaderWriter, 578 ): 579 with union_cpp_defn_target.indented( 580 f"union storage_t {{", 581 f"}};", 582 ): 583 union_cpp_defn_target.writelns( 584 f"storage_t() {{}}", 585 f"~storage_t() {{}}", 586 ) 587 for field in union.fields: 588 if field.ty_ref is None: 589 continue 590 type_cpp_info = TypeCppInfo.get(self.am, field.ty_ref.resolved_ty) 591 union_cpp_defn_target.writelns( 592 f"{type_cpp_info.as_owner} {field.name};", 593 ) 594 595 def gen_union_properties( 596 self, 597 union: UnionDecl, 598 union_abi_info: UnionABIInfo, 599 union_cpp_info: UnionCppInfo, 600 union_cpp_defn_target: CHeaderWriter, 601 ): 602 union_cpp_defn_target.writelns( 603 f"tag_t m_tag;", 604 f"storage_t m_data;", 605 ) 606 607 def gen_union_basic_methods( 608 self, 609 union: UnionDecl, 610 union_abi_info: UnionABIInfo, 611 union_cpp_info: UnionCppInfo, 612 union_cpp_defn_target: CHeaderWriter, 613 ): 614 # copy constructor 615 with union_cpp_defn_target.indented( 616 f"{union_cpp_info.name}({union_cpp_info.name} const& other) : m_tag(other.m_tag) {{", 617 f"}}", 618 ): 619 with union_cpp_defn_target.indented( 620 f"switch (m_tag) {{", 621 f"}}", 622 indent="", 623 ): 624 for field in union.fields: 625 if field.ty_ref is None: 626 continue 627 with union_cpp_defn_target.indented( 628 f"case tag_t::{field.name}: {{", 629 f"}}", 630 ): 631 union_cpp_defn_target.writelns( 632 f"new (&m_data.{field.name}) decltype(m_data.{field.name})(other.m_data.{field.name});", 633 f"break;", 634 ) 635 with union_cpp_defn_target.indented( 636 f"default: {{", 637 f"}}", 638 ): 639 union_cpp_defn_target.writelns( 640 f"break;", 641 ) 642 # move constructor 643 with union_cpp_defn_target.indented( 644 f"{union_cpp_info.name}({union_cpp_info.name}&& other) : m_tag(other.m_tag) {{", 645 f"}}", 646 ): 647 with union_cpp_defn_target.indented( 648 f"switch (m_tag) {{", 649 f"}}", 650 indent="", 651 ): 652 for field in union.fields: 653 if field.ty_ref is None: 654 continue 655 with union_cpp_defn_target.indented( 656 f"case tag_t::{field.name}: {{", 657 f"}}", 658 ): 659 union_cpp_defn_target.writelns( 660 f"new (&m_data.{field.name}) decltype(m_data.{field.name})(::std::move(other.m_data.{field.name}));", 661 f"break;", 662 ) 663 with union_cpp_defn_target.indented( 664 f"default: {{", 665 f"}}", 666 ): 667 union_cpp_defn_target.writelns( 668 f"break;", 669 ) 670 # copy assignment 671 with union_cpp_defn_target.indented( 672 f"{union_cpp_info.name}& operator=({union_cpp_info.name} const& other) {{", 673 f"}}", 674 ): 675 with union_cpp_defn_target.indented( 676 f"if (this != &other) {{", 677 f"}}", 678 ): 679 union_cpp_defn_target.writelns( 680 f"::std::destroy_at(this);", 681 f"new (this) {union_cpp_info.name}(other);", 682 ) 683 union_cpp_defn_target.writelns( 684 f"return *this;", 685 ) 686 # move assignment 687 with union_cpp_defn_target.indented( 688 f"{union_cpp_info.name}& operator=({union_cpp_info.name}&& other) {{", 689 f"}}", 690 ): 691 with union_cpp_defn_target.indented( 692 f"if (this != &other) {{", 693 f"}}", 694 ): 695 union_cpp_defn_target.writelns( 696 f"::std::destroy_at(this);", 697 f"new (this) {union_cpp_info.name}(::std::move(other));", 698 ) 699 union_cpp_defn_target.writelns( 700 f"return *this;", 701 ) 702 # destructor 703 with union_cpp_defn_target.indented( 704 f"~{union_cpp_info.name}() {{", 705 f"}}", 706 ): 707 with union_cpp_defn_target.indented( 708 f"switch (m_tag) {{", 709 f"}}", 710 indent="", 711 ): 712 for field in union.fields: 713 if field.ty_ref is None: 714 continue 715 with union_cpp_defn_target.indented( 716 f"case tag_t::{field.name}: {{", 717 f"}}", 718 ): 719 union_cpp_defn_target.writelns( 720 f"::std::destroy_at(&m_data.{field.name});", 721 f"break;", 722 ) 723 with union_cpp_defn_target.indented( 724 f"default: {{", 725 f"}}", 726 ): 727 union_cpp_defn_target.writelns( 728 f"break;", 729 ) 730 731 def gen_union_utils( 732 self, 733 union: UnionDecl, 734 union_abi_info: UnionABIInfo, 735 union_cpp_info: UnionCppInfo, 736 union_cpp_defn_target: CHeaderWriter, 737 ): 738 # in place constructor 739 for field in union.fields: 740 if field.ty_ref is None: 741 union_cpp_defn_target.writelns( 742 f"{union_cpp_info.name}(::taihe::static_tag_t<tag_t::{field.name}>) : m_tag(tag_t::{field.name}) {{}}", 743 ) 744 else: 745 union_cpp_defn_target.writelns( 746 f"template<typename... Args>", 747 ) 748 with union_cpp_defn_target.indented( 749 f"{union_cpp_info.name}(::taihe::static_tag_t<tag_t::{field.name}>, Args&&... args) : m_tag(tag_t::{field.name}) {{", 750 f"}}", 751 ): 752 union_cpp_defn_target.writelns( 753 f"new (&m_data.{field.name}) decltype(m_data.{field.name})(::std::forward<Args>(args)...);", 754 ) 755 # creator 756 union_cpp_defn_target.writelns( 757 f"template<tag_t tag, typename... Args>", 758 ) 759 with union_cpp_defn_target.indented( 760 f"static {union_cpp_info.name} make(Args&&... args) {{", 761 f"}}", 762 ): 763 union_cpp_defn_target.writelns( 764 f"return {union_cpp_info.name}(::taihe::static_tag<tag>, ::std::forward<Args>(args)...);", 765 ) 766 # emplacement 767 union_cpp_defn_target.writelns( 768 f"template<tag_t tag, typename... Args>", 769 ) 770 with union_cpp_defn_target.indented( 771 f"{union_cpp_info.name} const& emplace(Args&&... args) {{", 772 f"}}", 773 ): 774 union_cpp_defn_target.writelns( 775 f"::std::destroy_at(this);", 776 f"new (this) {union_cpp_info.name}(::taihe::static_tag<tag>, ::std::forward<Args>(args)...);", 777 f"return *this;", 778 ) 779 # non-const reference getter 780 union_cpp_defn_target.writelns( 781 f"template<tag_t tag>", 782 ) 783 with union_cpp_defn_target.indented( 784 f"auto& get_ref() {{", 785 f"}}", 786 ): 787 for field in union.fields: 788 if field.ty_ref is None: 789 continue 790 with union_cpp_defn_target.indented( 791 f"if constexpr (tag == tag_t::{field.name}) {{", 792 f"}}", 793 ): 794 union_cpp_defn_target.writelns( 795 f"return m_data.{field.name};", 796 ) 797 # non-const pointer getter 798 union_cpp_defn_target.writelns( 799 f"template<tag_t tag>", 800 ) 801 with union_cpp_defn_target.indented( 802 f"auto* get_ptr() {{", 803 f"}}", 804 ): 805 union_cpp_defn_target.writelns( 806 f"return m_tag == tag ? &get_ref<tag>() : nullptr;", 807 ) 808 # const reference getter 809 union_cpp_defn_target.writelns( 810 f"template<tag_t tag>", 811 ) 812 with union_cpp_defn_target.indented( 813 f"auto const& get_ref() const {{", 814 f"}}", 815 ): 816 for field in union.fields: 817 if field.ty_ref is None: 818 continue 819 with union_cpp_defn_target.indented( 820 f"if constexpr (tag == tag_t::{field.name}) {{", 821 f"}}", 822 ): 823 union_cpp_defn_target.writelns( 824 f"return m_data.{field.name};", 825 ) 826 # const pointer getter 827 union_cpp_defn_target.writelns( 828 f"template<tag_t tag>", 829 ) 830 with union_cpp_defn_target.indented( 831 f"auto const* get_ptr() const {{", 832 f"}}", 833 ): 834 union_cpp_defn_target.writelns( 835 f"return m_tag == tag ? &get_ref<tag>() : nullptr;", 836 ) 837 # tag checker 838 union_cpp_defn_target.writelns( 839 f"template<tag_t tag>", 840 ) 841 with union_cpp_defn_target.indented( 842 f"bool holds() const {{", 843 f"}}", 844 ): 845 union_cpp_defn_target.writelns( 846 f"return m_tag == tag;", 847 ) 848 # tag getter 849 with union_cpp_defn_target.indented( 850 f"tag_t get_tag() const {{", 851 f"}}", 852 ): 853 union_cpp_defn_target.writelns( 854 f"return m_tag;", 855 ) 856 # non-const visitor 857 union_cpp_defn_target.writelns( 858 f"template<typename Visitor>", 859 ) 860 with union_cpp_defn_target.indented( 861 f"auto accept_template(Visitor&& visitor) {{", 862 f"}}", 863 ): 864 with union_cpp_defn_target.indented( 865 f"switch (m_tag) {{", 866 f"}}", 867 indent="", 868 ): 869 for field in union.fields: 870 with union_cpp_defn_target.indented( 871 f"case tag_t::{field.name}: {{", 872 f"}}", 873 ): 874 result = f"::taihe::static_tag<tag_t::{field.name}>" 875 if field.ty_ref: 876 result += f", m_data.{field.name}" 877 union_cpp_defn_target.writelns( 878 f"return visitor({result});", 879 ) 880 # const visitor 881 union_cpp_defn_target.writelns( 882 f"template<typename Visitor>", 883 ) 884 with union_cpp_defn_target.indented( 885 f"auto accept_template(Visitor&& visitor) const {{", 886 f"}}", 887 ): 888 with union_cpp_defn_target.indented( 889 f"switch (m_tag) {{", 890 f"}}", 891 indent="", 892 ): 893 for field in union.fields: 894 with union_cpp_defn_target.indented( 895 f"case tag_t::{field.name}: {{", 896 f"}}", 897 ): 898 result = f"::taihe::static_tag<tag_t::{field.name}>" 899 if field.ty_ref: 900 result += f", m_data.{field.name}" 901 union_cpp_defn_target.writelns( 902 f"return visitor({result});", 903 ) 904 905 def gen_union_named_utils( 906 self, 907 union: UnionDecl, 908 union_abi_info: UnionABIInfo, 909 union_cpp_info: UnionCppInfo, 910 union_cpp_defn_target: CHeaderWriter, 911 ): 912 for field in union.fields: 913 # creator 914 union_cpp_defn_target.writelns( 915 f"template<typename... Args>", 916 ) 917 with union_cpp_defn_target.indented( 918 f"static {union_cpp_info.name} make_{field.name}(Args&&... args) {{", 919 f"}}", 920 ): 921 union_cpp_defn_target.writelns( 922 f"return make<tag_t::{field.name}>(::std::forward<Args>(args)...);", 923 ) 924 # emplacement 925 union_cpp_defn_target.writelns( 926 f"template<typename... Args>", 927 ) 928 with union_cpp_defn_target.indented( 929 f"{union_cpp_info.name} const& emplace_{field.name}(Args&&... args) {{", 930 f"}}", 931 ): 932 union_cpp_defn_target.writelns( 933 f"return emplace<tag_t::{field.name}>(::std::forward<Args>(args)...);", 934 ) 935 # tag checker 936 with union_cpp_defn_target.indented( 937 f"bool holds_{field.name}() const {{", 938 f"}}", 939 ): 940 union_cpp_defn_target.writelns( 941 f"return holds<tag_t::{field.name}>();", 942 ) 943 if field.ty_ref is None: 944 continue 945 # non-const pointer getter 946 with union_cpp_defn_target.indented( 947 f"auto* get_{field.name}_ptr() {{", 948 f"}}", 949 ): 950 union_cpp_defn_target.writelns( 951 f"return get_ptr<tag_t::{field.name}>();", 952 ) 953 # const pointer getter 954 with union_cpp_defn_target.indented( 955 f"auto const* get_{field.name}_ptr() const {{", 956 f"}}", 957 ): 958 union_cpp_defn_target.writelns( 959 f"return get_ptr<tag_t::{field.name}>();", 960 ) 961 # non-const reference getter 962 with union_cpp_defn_target.indented( 963 f"auto& get_{field.name}_ref() {{", 964 f"}}", 965 ): 966 union_cpp_defn_target.writelns( 967 f"return get_ref<tag_t::{field.name}>();", 968 ) 969 # const reference getter 970 with union_cpp_defn_target.indented( 971 f"auto const& get_{field.name}_ref() const {{", 972 f"}}", 973 ): 974 union_cpp_defn_target.writelns( 975 f"return get_ref<tag_t::{field.name}>();", 976 ) 977 # non-const visitor 978 union_cpp_defn_target.writelns( 979 f"template<typename Visitor>", 980 ) 981 with union_cpp_defn_target.indented( 982 f"auto accept(Visitor&& visitor) {{", 983 f"}}", 984 ): 985 with union_cpp_defn_target.indented( 986 f"switch (m_tag) {{", 987 f"}}", 988 indent="", 989 ): 990 for field in union.fields: 991 with union_cpp_defn_target.indented( 992 f"case tag_t::{field.name}: {{", 993 f"}}", 994 ): 995 result = "" if field.ty_ref is None else f"m_data.{field.name}" 996 union_cpp_defn_target.writelns( 997 f"return visitor.{field.name}({result});", 998 ) 999 # const visitor 1000 union_cpp_defn_target.writelns( 1001 f"template<typename Visitor>", 1002 ) 1003 with union_cpp_defn_target.indented( 1004 f"auto accept(Visitor&& visitor) const {{", 1005 f"}}", 1006 ): 1007 with union_cpp_defn_target.indented( 1008 f"switch (m_tag) {{", 1009 f"}}", 1010 indent="", 1011 ): 1012 for field in union.fields: 1013 with union_cpp_defn_target.indented( 1014 f"case tag_t::{field.name}: {{", 1015 f"}}", 1016 ): 1017 result = "" if field.ty_ref is None else f"m_data.{field.name}" 1018 union_cpp_defn_target.writelns( 1019 f"return visitor.{field.name}({result});", 1020 ) 1021 1022 def gen_union_same( 1023 self, 1024 union: UnionDecl, 1025 union_abi_info: UnionABIInfo, 1026 union_cpp_info: UnionCppInfo, 1027 union_cpp_defn_target: CHeaderWriter, 1028 ): 1029 with union_cpp_defn_target.indented( 1030 f"namespace {union_cpp_info.namespace} {{", 1031 f"}}", 1032 indent="", 1033 ): 1034 with union_cpp_defn_target.indented( 1035 f"inline bool operator==({union_cpp_info.as_param} lhs, {union_cpp_info.as_param} rhs) {{", 1036 f"}}", 1037 ): 1038 result = "false" 1039 for field in union.fields: 1040 cond = f"lhs.holds_{field.name}() && rhs.holds_{field.name}()" 1041 if field.ty_ref: 1042 cond = f"{cond} && lhs.get_{field.name}_ref() == rhs.get_{field.name}_ref()" 1043 result = f"{result} || ({cond})" 1044 union_cpp_defn_target.writelns( 1045 f"return {result};", 1046 ) 1047 1048 def gen_union_hash( 1049 self, 1050 union: UnionDecl, 1051 union_abi_info: UnionABIInfo, 1052 union_cpp_info: UnionCppInfo, 1053 union_cpp_defn_target: CHeaderWriter, 1054 ): 1055 with union_cpp_defn_target.indented( 1056 f"template<> struct ::std::hash<{union_cpp_info.full_name}> {{", 1057 f"}};", 1058 ): 1059 with union_cpp_defn_target.indented( 1060 f"size_t operator()({union_cpp_info.as_param} val) const {{", 1061 f"}}", 1062 ): 1063 with union_cpp_defn_target.indented( 1064 f"switch (val.get_tag()) {{", 1065 f"}}", 1066 indent="", 1067 ): 1068 for field in union.fields: 1069 with union_cpp_defn_target.indented( 1070 f"case {union_cpp_info.full_name}::tag_t::{field.name}: {{", 1071 f"}}", 1072 ): 1073 val = "0x9e3779b9 + (seed << 6) + (seed >> 2)" 1074 if field.ty_ref: 1075 val = f"{val} + ::std::hash<{TypeCppInfo.get(self.am, field.ty_ref.resolved_ty).as_owner}>()(val.get_{field.name}_ref())" 1076 val = f"seed ^ ({val})" 1077 union_cpp_defn_target.writelns( 1078 f"::std::size_t seed = (::std::size_t){union_cpp_info.full_name}::tag_t::{field.name};", 1079 f"return {val};", 1080 ) 1081 1082 def gen_union_impl_file( 1083 self, 1084 union: UnionDecl, 1085 union_abi_info: UnionABIInfo, 1086 union_cpp_info: UnionCppInfo, 1087 ): 1088 with CHeaderWriter( 1089 self.om, 1090 f"include/{union_cpp_info.impl_header}", 1091 FileKind.C_HEADER, 1092 ) as union_cpp_impl_target: 1093 union_cpp_impl_target.add_include(union_cpp_info.defn_header) 1094 union_cpp_impl_target.add_include(union_abi_info.impl_header) 1095 for field in union.fields: 1096 if field.ty_ref is None: 1097 continue 1098 type_cpp_info = TypeCppInfo.get(self.am, field.ty_ref.resolved_ty) 1099 union_cpp_impl_target.add_include(*type_cpp_info.impl_headers) 1100 1101 def gen_struct_decl_file( 1102 self, 1103 struct: StructDecl, 1104 struct_abi_info: StructABIInfo, 1105 struct_cpp_info: StructCppInfo, 1106 ): 1107 with CHeaderWriter( 1108 self.om, 1109 f"include/{struct_cpp_info.decl_header}", 1110 FileKind.C_HEADER, 1111 ) as struct_cpp_decl_target: 1112 struct_cpp_decl_target.add_include("taihe/common.hpp") 1113 struct_cpp_decl_target.add_include(struct_abi_info.decl_header) 1114 with struct_cpp_decl_target.indented( 1115 f"namespace {struct_cpp_info.namespace} {{", 1116 f"}}", 1117 indent="", 1118 ): 1119 struct_cpp_decl_target.writelns( 1120 f"struct {struct_cpp_info.name};", 1121 ) 1122 with struct_cpp_decl_target.indented( 1123 f"namespace taihe {{", 1124 f"}}", 1125 indent="", 1126 ): 1127 struct_cpp_decl_target.writelns( 1128 f"template<>", 1129 ) 1130 with struct_cpp_decl_target.indented( 1131 f"struct as_abi<{struct_cpp_info.as_owner}> {{", 1132 f"}};", 1133 ): 1134 struct_cpp_decl_target.writelns( 1135 f"using type = {struct_abi_info.as_owner};", 1136 ) 1137 struct_cpp_decl_target.writelns( 1138 f"template<>", 1139 ) 1140 with struct_cpp_decl_target.indented( 1141 f"struct as_abi<{struct_cpp_info.as_param}> {{", 1142 f"}};", 1143 ): 1144 struct_cpp_decl_target.writelns( 1145 f"using type = {struct_abi_info.as_param};", 1146 ) 1147 struct_cpp_decl_target.writelns( 1148 f"template<>", 1149 ) 1150 with struct_cpp_decl_target.indented( 1151 f"struct as_param<{struct_cpp_info.as_owner}> {{", 1152 f"}};", 1153 ): 1154 struct_cpp_decl_target.writelns( 1155 f"using type = {struct_cpp_info.as_param};", 1156 ) 1157 1158 def gen_struct_defn_file( 1159 self, 1160 struct: StructDecl, 1161 struct_abi_info: StructABIInfo, 1162 struct_cpp_info: StructCppInfo, 1163 ): 1164 with CHeaderWriter( 1165 self.om, 1166 f"include/{struct_cpp_info.defn_header}", 1167 FileKind.CPP_HEADER, 1168 ) as struct_cpp_defn_target: 1169 struct_cpp_defn_target.add_include(struct_cpp_info.decl_header) 1170 struct_cpp_defn_target.add_include(struct_abi_info.defn_header) 1171 for field in struct.fields: 1172 type_cpp_info = TypeCppInfo.get(self.am, field.ty_ref.resolved_ty) 1173 struct_cpp_defn_target.add_include(*type_cpp_info.defn_headers) 1174 self.gen_struct_defn( 1175 struct, 1176 struct_abi_info, 1177 struct_cpp_info, 1178 struct_cpp_defn_target, 1179 ) 1180 self.gen_struct_same( 1181 struct, 1182 struct_abi_info, 1183 struct_cpp_info, 1184 struct_cpp_defn_target, 1185 ) 1186 self.gen_struct_hash( 1187 struct, 1188 struct_abi_info, 1189 struct_cpp_info, 1190 struct_cpp_defn_target, 1191 ) 1192 1193 def gen_struct_defn( 1194 self, 1195 struct: StructDecl, 1196 struct_abi_info: StructABIInfo, 1197 struct_cpp_info: StructCppInfo, 1198 struct_cpp_defn_target: CHeaderWriter, 1199 ): 1200 with struct_cpp_defn_target.indented( 1201 f"namespace {struct_cpp_info.namespace} {{", 1202 f"}}", 1203 indent="", 1204 ): 1205 with struct_cpp_defn_target.indented( 1206 f"struct {struct_cpp_info.name} {{", 1207 f"}};", 1208 ): 1209 for field in struct.fields: 1210 type_cpp_info = TypeCppInfo.get(self.am, field.ty_ref.resolved_ty) 1211 struct_cpp_defn_target.writelns( 1212 f"{type_cpp_info.as_owner} {field.name};", 1213 ) 1214 1215 def gen_struct_same( 1216 self, 1217 struct: StructDecl, 1218 struct_abi_info: StructABIInfo, 1219 struct_cpp_info: StructCppInfo, 1220 struct_cpp_defn_target: CHeaderWriter, 1221 ): 1222 with struct_cpp_defn_target.indented( 1223 f"namespace {struct_cpp_info.namespace} {{", 1224 f"}}", 1225 indent="", 1226 ): 1227 with struct_cpp_defn_target.indented( 1228 f"inline bool operator==({struct_cpp_info.as_param} lhs, {struct_cpp_info.as_param} rhs) {{", 1229 f"}}", 1230 ): 1231 result = "true" 1232 for field in struct.fields: 1233 result = f"{result} && lhs.{field.name} == rhs.{field.name}" 1234 struct_cpp_defn_target.writelns( 1235 f"return {result};", 1236 ) 1237 1238 def gen_struct_hash( 1239 self, 1240 struct: StructDecl, 1241 struct_abi_info: StructABIInfo, 1242 struct_cpp_info: StructCppInfo, 1243 struct_cpp_defn_target: CHeaderWriter, 1244 ): 1245 with struct_cpp_defn_target.indented( 1246 f"template<> struct ::std::hash<{struct_cpp_info.full_name}> {{", 1247 f"}};", 1248 ): 1249 with struct_cpp_defn_target.indented( 1250 f"size_t operator()({struct_cpp_info.as_param} val) const {{", 1251 f"}}", 1252 ): 1253 struct_cpp_defn_target.writelns( 1254 f"::std::size_t seed = 0;", 1255 ) 1256 for field in struct.fields: 1257 struct_cpp_defn_target.writelns( 1258 f"seed ^= ::std::hash<{TypeCppInfo.get(self.am, field.ty_ref.resolved_ty).as_owner}>()(val.{field.name}) + 0x9e3779b9 + (seed << 6) + (seed >> 2);", 1259 ) 1260 struct_cpp_defn_target.writelns( 1261 f"return seed;", 1262 ) 1263 1264 def gen_struct_impl_file( 1265 self, 1266 struct: StructDecl, 1267 struct_abi_info: StructABIInfo, 1268 struct_cpp_info: StructCppInfo, 1269 ): 1270 with CHeaderWriter( 1271 self.om, 1272 f"include/{struct_cpp_info.impl_header}", 1273 FileKind.C_HEADER, 1274 ) as struct_cpp_impl_target: 1275 struct_cpp_impl_target.add_include(struct_cpp_info.defn_header) 1276 struct_cpp_impl_target.add_include(struct_abi_info.impl_header) 1277 for field in struct.fields: 1278 type_cpp_info = TypeCppInfo.get(self.am, field.ty_ref.resolved_ty) 1279 struct_cpp_impl_target.add_include(*type_cpp_info.impl_headers) 1280 1281 def gen_iface_decl_file( 1282 self, 1283 iface: IfaceDecl, 1284 iface_abi_info: IfaceABIInfo, 1285 iface_cpp_info: IfaceCppInfo, 1286 ): 1287 with CHeaderWriter( 1288 self.om, 1289 f"include/{iface_cpp_info.decl_header}", 1290 FileKind.C_HEADER, 1291 ) as iface_cpp_decl_target: 1292 iface_cpp_decl_target.add_include("taihe/object.hpp") 1293 iface_cpp_decl_target.add_include(iface_abi_info.decl_header) 1294 with iface_cpp_decl_target.indented( 1295 f"namespace {iface_cpp_info.weakspace} {{", 1296 f"}}", 1297 indent="", 1298 ): 1299 iface_cpp_decl_target.writelns( 1300 f"struct {iface_cpp_info.weak_name};", 1301 ) 1302 with iface_cpp_decl_target.indented( 1303 f"namespace {iface_cpp_info.namespace} {{", 1304 f"}}", 1305 indent="", 1306 ): 1307 iface_cpp_decl_target.writelns( 1308 f"struct {iface_cpp_info.norm_name};", 1309 ) 1310 with iface_cpp_decl_target.indented( 1311 f"namespace taihe {{", 1312 f"}}", 1313 indent="", 1314 ): 1315 iface_cpp_decl_target.writelns( 1316 f"template<>", 1317 ) 1318 with iface_cpp_decl_target.indented( 1319 f"struct as_abi<{iface_cpp_info.as_owner}> {{", 1320 f"}};", 1321 ): 1322 iface_cpp_decl_target.writelns( 1323 f"using type = {iface_abi_info.as_owner};", 1324 ) 1325 iface_cpp_decl_target.writelns( 1326 f"template<>", 1327 ) 1328 with iface_cpp_decl_target.indented( 1329 f"struct as_abi<{iface_cpp_info.as_param}> {{", 1330 f"}};", 1331 ): 1332 iface_cpp_decl_target.writelns( 1333 f"using type = {iface_abi_info.as_param};", 1334 ) 1335 iface_cpp_decl_target.writelns( 1336 f"template<>", 1337 ) 1338 with iface_cpp_decl_target.indented( 1339 f"struct as_param<{iface_cpp_info.as_owner}> {{", 1340 f"}};", 1341 ): 1342 iface_cpp_decl_target.writelns( 1343 f"using type = {iface_cpp_info.as_param};", 1344 ) 1345 1346 def gen_iface_defn_file( 1347 self, 1348 iface: IfaceDecl, 1349 iface_abi_info: IfaceABIInfo, 1350 iface_cpp_info: IfaceCppInfo, 1351 ): 1352 with CHeaderWriter( 1353 self.om, 1354 f"include/{iface_cpp_info.defn_header}", 1355 FileKind.CPP_HEADER, 1356 ) as iface_cpp_defn_target: 1357 iface_cpp_defn_target.add_include(iface_cpp_info.decl_header) 1358 iface_cpp_defn_target.add_include(iface_abi_info.defn_header) 1359 for ancestor, info in iface_abi_info.ancestor_dict.items(): 1360 if ancestor is iface: 1361 continue 1362 ancestor_cpp_info = IfaceCppInfo.get(self.am, ancestor) 1363 iface_cpp_defn_target.add_include(ancestor_cpp_info.defn_header) 1364 self.gen_iface_view_defn( 1365 iface, 1366 iface_abi_info, 1367 iface_cpp_info, 1368 iface_cpp_defn_target, 1369 ) 1370 self.gen_iface_holder_defn( 1371 iface, 1372 iface_abi_info, 1373 iface_cpp_info, 1374 iface_cpp_defn_target, 1375 ) 1376 self.gen_iface_same( 1377 iface, 1378 iface_abi_info, 1379 iface_cpp_info, 1380 iface_cpp_defn_target, 1381 ) 1382 self.gen_iface_hash( 1383 iface, 1384 iface_abi_info, 1385 iface_cpp_info, 1386 iface_cpp_defn_target, 1387 ) 1388 1389 def gen_iface_view_defn( 1390 self, 1391 iface: IfaceDecl, 1392 iface_abi_info: IfaceABIInfo, 1393 iface_cpp_info: IfaceCppInfo, 1394 iface_cpp_defn_target: CHeaderWriter, 1395 ): 1396 with iface_cpp_defn_target.indented( 1397 f"namespace {iface_cpp_info.weakspace} {{", 1398 f"}}", 1399 indent="", 1400 ): 1401 with iface_cpp_defn_target.indented( 1402 f"struct {iface_cpp_info.weak_name} {{", 1403 f"}};", 1404 ): 1405 iface_cpp_defn_target.writelns( 1406 f"static constexpr bool is_holder = false;", 1407 ) 1408 iface_cpp_defn_target.writelns( 1409 f"{iface_abi_info.as_owner} m_handle;", 1410 ) 1411 iface_cpp_defn_target.writelns( 1412 f"explicit {iface_cpp_info.weak_name}({iface_abi_info.as_param} handle) : m_handle(handle) {{}}", 1413 ) 1414 self.gen_iface_view_dynamic_cast( 1415 iface, 1416 iface_abi_info, 1417 iface_cpp_info, 1418 iface_cpp_defn_target, 1419 ) 1420 self.gen_iface_view_static_cast( 1421 iface, 1422 iface_abi_info, 1423 iface_cpp_info, 1424 iface_cpp_defn_target, 1425 ) 1426 self.gen_iface_user_methods_decl( 1427 iface, 1428 iface_abi_info, 1429 iface_cpp_info, 1430 iface_cpp_defn_target, 1431 ) 1432 self.gen_iface_impl_methods_decl( 1433 iface, 1434 iface_abi_info, 1435 iface_cpp_info, 1436 iface_cpp_defn_target, 1437 ) 1438 self.gen_iface_ftbl_decl( 1439 iface, 1440 iface_abi_info, 1441 iface_cpp_info, 1442 iface_cpp_defn_target, 1443 ) 1444 self.gen_iface_vtbl_impl( 1445 iface, 1446 iface_abi_info, 1447 iface_cpp_info, 1448 iface_cpp_defn_target, 1449 ) 1450 self.gen_iface_idmap_impl( 1451 iface, 1452 iface_abi_info, 1453 iface_cpp_info, 1454 iface_cpp_defn_target, 1455 ) 1456 self.gen_iface_infos( 1457 iface, 1458 iface_abi_info, 1459 iface_cpp_info, 1460 iface_cpp_defn_target, 1461 ) 1462 self.gen_iface_utils( 1463 iface, 1464 iface_abi_info, 1465 iface_cpp_info, 1466 iface_cpp_defn_target, 1467 ) 1468 1469 def gen_iface_view_dynamic_cast( 1470 self, 1471 iface: IfaceDecl, 1472 iface_abi_info: IfaceABIInfo, 1473 iface_cpp_info: IfaceCppInfo, 1474 iface_cpp_defn_target: CHeaderWriter, 1475 ): 1476 with iface_cpp_defn_target.indented( 1477 f"operator ::taihe::data_view() const& {{", 1478 f"}}", 1479 ): 1480 iface_cpp_defn_target.writelns( 1481 f"return ::taihe::data_view(this->m_handle.data_ptr);", 1482 ) 1483 with iface_cpp_defn_target.indented( 1484 f"operator ::taihe::data_holder() const& {{", 1485 f"}}", 1486 ): 1487 iface_cpp_defn_target.writelns( 1488 f"return ::taihe::data_holder(tobj_dup(this->m_handle.data_ptr));", 1489 ) 1490 with iface_cpp_defn_target.indented( 1491 f"explicit {iface_cpp_info.weak_name}(::taihe::data_view other) : {iface_cpp_info.weak_name}({{", 1492 f"}}) {{}}", 1493 ): 1494 iface_cpp_defn_target.writelns( 1495 f"{iface_abi_info.dynamic_cast}(other.data_ptr->rtti_ptr),", 1496 f"other.data_ptr,", 1497 ) 1498 1499 def gen_iface_view_static_cast( 1500 self, 1501 iface: IfaceDecl, 1502 iface_abi_info: IfaceABIInfo, 1503 iface_cpp_info: IfaceCppInfo, 1504 iface_cpp_defn_target: CHeaderWriter, 1505 ): 1506 for ancestor, info in iface_abi_info.ancestor_dict.items(): 1507 if ancestor is iface: 1508 continue 1509 ancestor_cpp_info = IfaceCppInfo.get(self.am, ancestor) 1510 with iface_cpp_defn_target.indented( 1511 f"operator {ancestor_cpp_info.full_weak_name}() const& {{", 1512 f"}}", 1513 ): 1514 with iface_cpp_defn_target.indented( 1515 f"return {ancestor_cpp_info.full_weak_name}({{", 1516 f"}});", 1517 ): 1518 iface_cpp_defn_target.writelns( 1519 f"{info.static_cast}(this->m_handle.vtbl_ptr),", 1520 f"this->m_handle.data_ptr,", 1521 ) 1522 with iface_cpp_defn_target.indented( 1523 f"operator {ancestor_cpp_info.full_norm_name}() const& {{", 1524 f"}}", 1525 ): 1526 with iface_cpp_defn_target.indented( 1527 f"return {ancestor_cpp_info.full_norm_name}({{", 1528 f"}});", 1529 ): 1530 iface_cpp_defn_target.writelns( 1531 f"{info.static_cast}(this->m_handle.vtbl_ptr),", 1532 f"tobj_dup(this->m_handle.data_ptr),", 1533 ) 1534 1535 def gen_iface_user_methods_decl( 1536 self, 1537 iface: IfaceDecl, 1538 iface_abi_info: IfaceABIInfo, 1539 iface_cpp_info: IfaceCppInfo, 1540 iface_cpp_defn_target: CHeaderWriter, 1541 ): 1542 iface_cpp_defn_target.writelns( 1543 f"struct virtual_type;", 1544 ) 1545 1546 def gen_iface_impl_methods_decl( 1547 self, 1548 iface: IfaceDecl, 1549 iface_abi_info: IfaceABIInfo, 1550 iface_cpp_info: IfaceCppInfo, 1551 iface_cpp_defn_target: CHeaderWriter, 1552 ): 1553 iface_cpp_defn_target.writelns( 1554 f"template<typename Impl>", 1555 f"struct methods_impl;", 1556 ) 1557 1558 def gen_iface_ftbl_decl( 1559 self, 1560 iface: IfaceDecl, 1561 iface_abi_info: IfaceABIInfo, 1562 iface_cpp_info: IfaceCppInfo, 1563 iface_cpp_defn_target: CHeaderWriter, 1564 ): 1565 iface_cpp_defn_target.writelns( 1566 f"template<typename Impl>", 1567 f"static const {iface_abi_info.ftable} ftbl_impl;", 1568 ) 1569 1570 def gen_iface_vtbl_impl( 1571 self, 1572 iface: IfaceDecl, 1573 iface_abi_info: IfaceABIInfo, 1574 iface_cpp_info: IfaceCppInfo, 1575 iface_cpp_defn_target: CHeaderWriter, 1576 ): 1577 iface_cpp_defn_target.writelns( 1578 f"template<typename Impl>", 1579 ) 1580 with iface_cpp_defn_target.indented( 1581 f"static constexpr {iface_abi_info.vtable} vtbl_impl = {{", 1582 f"}};", 1583 ): 1584 for ancestor_info in iface_abi_info.ancestor_list: 1585 ancestor_cpp_info = IfaceCppInfo.get(self.am, ancestor_info.iface) 1586 iface_cpp_defn_target.writelns( 1587 f".{ancestor_info.ftbl_ptr} = &{ancestor_cpp_info.full_weak_name}::template ftbl_impl<Impl>,", 1588 ) 1589 1590 def gen_iface_idmap_impl( 1591 self, 1592 iface: IfaceDecl, 1593 iface_abi_info: IfaceABIInfo, 1594 iface_cpp_info: IfaceCppInfo, 1595 iface_cpp_defn_target: CHeaderWriter, 1596 ): 1597 iface_cpp_defn_target.writelns( 1598 f"template<typename Impl>", 1599 ) 1600 with iface_cpp_defn_target.indented( 1601 f"static constexpr struct IdMapItem idmap_impl[{len(iface_abi_info.ancestor_dict)}] = {{", 1602 f"}};", 1603 ): 1604 for ancestor, info in iface_abi_info.ancestor_dict.items(): 1605 ancestor_abi_info = IfaceABIInfo.get(self.am, ancestor) 1606 iface_cpp_defn_target.writelns( 1607 f"{{&{ancestor_abi_info.iid}, &vtbl_impl<Impl>.{info.ftbl_ptr}}},", 1608 ) 1609 1610 def gen_iface_infos( 1611 self, 1612 iface: IfaceDecl, 1613 iface_abi_info: IfaceABIInfo, 1614 iface_cpp_info: IfaceCppInfo, 1615 iface_cpp_defn_target: CHeaderWriter, 1616 ): 1617 iface_cpp_defn_target.writelns( 1618 f"using vtable_type = {iface_abi_info.vtable};", 1619 f"using view_type = {iface_cpp_info.full_weak_name};", 1620 f"using holder_type = {iface_cpp_info.full_norm_name};", 1621 f"using abi_type = {iface_abi_info.mangled_name};", 1622 ) 1623 1624 def gen_iface_utils( 1625 self, 1626 iface: IfaceDecl, 1627 iface_abi_info: IfaceABIInfo, 1628 iface_cpp_info: IfaceCppInfo, 1629 iface_cpp_defn_target: CHeaderWriter, 1630 ): 1631 with iface_cpp_defn_target.indented( 1632 f"bool is_error() const& {{", 1633 f"}}", 1634 ): 1635 iface_cpp_defn_target.writelns( 1636 f"return m_handle.vtbl_ptr == nullptr;", 1637 ) 1638 with iface_cpp_defn_target.indented( 1639 f"virtual_type const& operator*() const& {{", 1640 f"}}", 1641 ): 1642 iface_cpp_defn_target.writelns( 1643 f"return *reinterpret_cast<virtual_type const*>(&m_handle);", 1644 ) 1645 with iface_cpp_defn_target.indented( 1646 f"virtual_type const* operator->() const& {{", 1647 f"}}", 1648 ): 1649 iface_cpp_defn_target.writelns( 1650 f"return reinterpret_cast<virtual_type const*>(&m_handle);", 1651 ) 1652 1653 def gen_iface_holder_defn( 1654 self, 1655 iface: IfaceDecl, 1656 iface_abi_info: IfaceABIInfo, 1657 iface_cpp_info: IfaceCppInfo, 1658 iface_cpp_defn_target: CHeaderWriter, 1659 ): 1660 with iface_cpp_defn_target.indented( 1661 f"namespace {iface_cpp_info.namespace} {{", 1662 f"}}", 1663 indent="", 1664 ): 1665 with iface_cpp_defn_target.indented( 1666 f"struct {iface_cpp_info.norm_name} : public {iface_cpp_info.full_weak_name} {{", 1667 f"}};", 1668 ): 1669 iface_cpp_defn_target.writelns( 1670 f"static constexpr bool is_holder = true;", 1671 ) 1672 iface_cpp_defn_target.writelns( 1673 f"explicit {iface_cpp_info.norm_name}({iface_abi_info.as_owner} handle) : {iface_cpp_info.full_weak_name}(handle) {{}}", 1674 ) 1675 with iface_cpp_defn_target.indented( 1676 f"{iface_cpp_info.norm_name}& operator=({iface_cpp_info.full_norm_name} other) {{", 1677 f"}}", 1678 ): 1679 iface_cpp_defn_target.writelns( 1680 f"::std::swap(this->m_handle, other.m_handle);", 1681 f"return *this;", 1682 ) 1683 with iface_cpp_defn_target.indented( 1684 f"~{iface_cpp_info.norm_name}() {{", 1685 f"}}", 1686 ): 1687 iface_cpp_defn_target.writelns( 1688 f"tobj_drop(this->m_handle.data_ptr);", 1689 ) 1690 self.gen_iface_holder_dynamic_cast( 1691 iface, 1692 iface_abi_info, 1693 iface_cpp_info, 1694 iface_cpp_defn_target, 1695 ) 1696 self.gen_iface_holder_static_cast( 1697 iface, 1698 iface_abi_info, 1699 iface_cpp_info, 1700 iface_cpp_defn_target, 1701 ) 1702 1703 def gen_iface_holder_dynamic_cast( 1704 self, 1705 iface: IfaceDecl, 1706 iface_abi_info: IfaceABIInfo, 1707 iface_cpp_info: IfaceCppInfo, 1708 iface_cpp_defn_target: CHeaderWriter, 1709 ): 1710 with iface_cpp_defn_target.indented( 1711 f"operator ::taihe::data_view() const& {{", 1712 f"}}", 1713 ): 1714 iface_cpp_defn_target.writelns( 1715 f"return ::taihe::data_view(this->m_handle.data_ptr);", 1716 ) 1717 with iface_cpp_defn_target.indented( 1718 f"operator ::taihe::data_holder() const& {{", 1719 f"}}", 1720 ): 1721 iface_cpp_defn_target.writelns( 1722 f"return ::taihe::data_holder(tobj_dup(this->m_handle.data_ptr));", 1723 ) 1724 with iface_cpp_defn_target.indented( 1725 f"operator ::taihe::data_holder() && {{", 1726 f"}}", 1727 ): 1728 iface_cpp_defn_target.writelns( 1729 f"return ::taihe::data_holder(std::exchange(this->m_handle.data_ptr, nullptr));", 1730 ) 1731 with iface_cpp_defn_target.indented( 1732 f"explicit {iface_cpp_info.norm_name}(::taihe::data_holder other) : {iface_cpp_info.norm_name}({{", 1733 f"}}) {{}}", 1734 ): 1735 iface_cpp_defn_target.writelns( 1736 f"{iface_abi_info.dynamic_cast}(other.data_ptr->rtti_ptr),", 1737 f"std::exchange(other.data_ptr, nullptr),", 1738 ) 1739 1740 def gen_iface_holder_static_cast( 1741 self, 1742 iface: IfaceDecl, 1743 iface_abi_info: IfaceABIInfo, 1744 iface_cpp_info: IfaceCppInfo, 1745 iface_cpp_defn_target: CHeaderWriter, 1746 ): 1747 with iface_cpp_defn_target.indented( 1748 f"{iface_cpp_info.norm_name}({iface_cpp_info.full_weak_name} const& other) : {iface_cpp_info.norm_name}({{", 1749 f"}}) {{}}", 1750 ): 1751 iface_cpp_defn_target.writelns( 1752 f"other.m_handle.vtbl_ptr,", 1753 f"tobj_dup(other.m_handle.data_ptr),", 1754 ) 1755 with iface_cpp_defn_target.indented( 1756 f"{iface_cpp_info.norm_name}({iface_cpp_info.full_norm_name} const& other) : {iface_cpp_info.norm_name}({{", 1757 f"}}) {{}}", 1758 ): 1759 iface_cpp_defn_target.writelns( 1760 f"other.m_handle.vtbl_ptr,", 1761 f"tobj_dup(other.m_handle.data_ptr),", 1762 ) 1763 with iface_cpp_defn_target.indented( 1764 f"{iface_cpp_info.norm_name}({iface_cpp_info.full_norm_name}&& other) : {iface_cpp_info.norm_name}({{", 1765 f"}}) {{}}", 1766 ): 1767 iface_cpp_defn_target.writelns( 1768 f"other.m_handle.vtbl_ptr,", 1769 f"std::exchange(other.m_handle.data_ptr, nullptr),", 1770 ) 1771 for ancestor, info in iface_abi_info.ancestor_dict.items(): 1772 if ancestor is iface: 1773 continue 1774 ancestor_cpp_info = IfaceCppInfo.get(self.am, ancestor) 1775 with iface_cpp_defn_target.indented( 1776 f"operator {ancestor_cpp_info.full_weak_name}() const& {{", 1777 f"}}", 1778 ): 1779 with iface_cpp_defn_target.indented( 1780 f"return {ancestor_cpp_info.full_weak_name}({{", 1781 f"}});", 1782 ): 1783 iface_cpp_defn_target.writelns( 1784 f"{info.static_cast}(this->m_handle.vtbl_ptr),", 1785 f"this->m_handle.data_ptr,", 1786 ) 1787 with iface_cpp_defn_target.indented( 1788 f"operator {ancestor_cpp_info.full_norm_name}() const& {{", 1789 f"}}", 1790 ): 1791 with iface_cpp_defn_target.indented( 1792 f"return {ancestor_cpp_info.full_norm_name}({{", 1793 f"}});", 1794 ): 1795 iface_cpp_defn_target.writelns( 1796 f"{info.static_cast}(this->m_handle.vtbl_ptr),", 1797 f"tobj_dup(this->m_handle.data_ptr),", 1798 ) 1799 with iface_cpp_defn_target.indented( 1800 f"operator {ancestor_cpp_info.full_norm_name}() && {{", 1801 f"}}", 1802 ): 1803 with iface_cpp_defn_target.indented( 1804 f"return {ancestor_cpp_info.full_norm_name}({{", 1805 f"}});", 1806 ): 1807 iface_cpp_defn_target.writelns( 1808 f"{info.static_cast}(this->m_handle.vtbl_ptr),", 1809 f"std::exchange(this->m_handle.data_ptr, nullptr),", 1810 ) 1811 1812 def gen_iface_same( 1813 self, 1814 iface: IfaceDecl, 1815 iface_abi_info: IfaceABIInfo, 1816 iface_cpp_info: IfaceCppInfo, 1817 iface_cpp_defn_target: CHeaderWriter, 1818 ): 1819 with iface_cpp_defn_target.indented( 1820 f"namespace {iface_cpp_info.weakspace} {{", 1821 f"}}", 1822 indent="", 1823 ): 1824 with iface_cpp_defn_target.indented( 1825 f"inline bool operator==({iface_cpp_info.as_param} lhs, {iface_cpp_info.as_param} rhs) {{", 1826 f"}}", 1827 ): 1828 iface_cpp_defn_target.writelns( 1829 f"return ::taihe::data_view(lhs) == ::taihe::data_view(rhs);", 1830 ) 1831 1832 def gen_iface_hash( 1833 self, 1834 iface: IfaceDecl, 1835 iface_abi_info: IfaceABIInfo, 1836 iface_cpp_info: IfaceCppInfo, 1837 iface_cpp_defn_target: CHeaderWriter, 1838 ): 1839 with iface_cpp_defn_target.indented( 1840 f"template<> struct ::std::hash<{iface_cpp_info.full_norm_name}> {{", 1841 f"}};", 1842 ): 1843 with iface_cpp_defn_target.indented( 1844 f"size_t operator()({iface_cpp_info.as_param} val) const {{", 1845 f"}}", 1846 ): 1847 iface_cpp_defn_target.writelns( 1848 f"return ::std::hash<::taihe::data_holder>()(val);", 1849 ) 1850 1851 def gen_iface_impl_file( 1852 self, 1853 iface: IfaceDecl, 1854 iface_abi_info: IfaceABIInfo, 1855 iface_cpp_info: IfaceCppInfo, 1856 ): 1857 with CHeaderWriter( 1858 self.om, 1859 f"include/{iface_cpp_info.impl_header}", 1860 FileKind.CPP_HEADER, 1861 ) as iface_cpp_impl_target: 1862 iface_cpp_impl_target.add_include(iface_cpp_info.defn_header) 1863 iface_cpp_impl_target.add_include(iface_abi_info.impl_header) 1864 for method in iface.methods: 1865 for param in method.params: 1866 type_cpp_info = TypeCppInfo.get(self.am, param.ty_ref.resolved_ty) 1867 iface_cpp_impl_target.add_include(*type_cpp_info.defn_headers) 1868 if return_ty_ref := method.return_ty_ref: 1869 type_cpp_info = TypeCppInfo.get(self.am, return_ty_ref.resolved_ty) 1870 iface_cpp_impl_target.add_include(*type_cpp_info.defn_headers) 1871 self.gen_iface_user_methods_impl( 1872 iface, 1873 iface_abi_info, 1874 iface_cpp_info, 1875 iface_cpp_impl_target, 1876 ) 1877 self.gen_iface_impl_methods_impl( 1878 iface, 1879 iface_abi_info, 1880 iface_cpp_info, 1881 iface_cpp_impl_target, 1882 ) 1883 self.gen_iface_ftbl_impl( 1884 iface, 1885 iface_abi_info, 1886 iface_cpp_info, 1887 iface_cpp_impl_target, 1888 ) 1889 for ancestor, info in iface_abi_info.ancestor_dict.items(): 1890 if ancestor is iface: 1891 continue 1892 ancestor_cpp_info = IfaceCppInfo.get(self.am, ancestor) 1893 iface_cpp_impl_target.add_include(ancestor_cpp_info.impl_header) 1894 for method in iface.methods: 1895 for param in method.params: 1896 type_cpp_info = TypeCppInfo.get(self.am, param.ty_ref.resolved_ty) 1897 iface_cpp_impl_target.add_include(*type_cpp_info.impl_headers) 1898 if return_ty_ref := method.return_ty_ref: 1899 type_cpp_info = TypeCppInfo.get(self.am, return_ty_ref.resolved_ty) 1900 iface_cpp_impl_target.add_include(*type_cpp_info.impl_headers) 1901 1902 def gen_iface_user_methods_impl( 1903 self, 1904 iface: IfaceDecl, 1905 iface_abi_info: IfaceABIInfo, 1906 iface_cpp_info: IfaceCppInfo, 1907 iface_cpp_impl_target: CHeaderWriter, 1908 ): 1909 with iface_cpp_impl_target.indented( 1910 f"struct {iface_cpp_info.full_weak_name}::virtual_type {{", 1911 f"}};", 1912 ): 1913 for method in iface.methods: 1914 method_abi_info = IfaceMethodABIInfo.get(self.am, method) 1915 method_cpp_info = IfaceMethodCppInfo.get(self.am, method) 1916 params_cpp = [] 1917 thiz = f"*reinterpret_cast<{iface_abi_info.mangled_name} const*>(this)" 1918 args_into_abi = [thiz] 1919 for param in method.params: 1920 type_cpp_info = TypeCppInfo.get(self.am, param.ty_ref.resolved_ty) 1921 params_cpp.append(f"{type_cpp_info.as_param} {param.name}") 1922 args_into_abi.append(type_cpp_info.pass_into_abi(param.name)) 1923 params_cpp_str = ", ".join(params_cpp) 1924 args_into_abi_str = ", ".join(args_into_abi) 1925 abi_result = f"{method_abi_info.mangled_name}({args_into_abi_str})" 1926 if return_ty_ref := method.return_ty_ref: 1927 type_cpp_info = TypeCppInfo.get(self.am, return_ty_ref.resolved_ty) 1928 cpp_return_ty_name = type_cpp_info.as_owner 1929 cpp_result = type_cpp_info.return_from_abi(abi_result) 1930 else: 1931 cpp_return_ty_name = "void" 1932 cpp_result = abi_result 1933 with iface_cpp_impl_target.indented( 1934 f"{cpp_return_ty_name} {method_cpp_info.call_name}({params_cpp_str}) const& {{", 1935 f"}}", 1936 ): 1937 iface_cpp_impl_target.writelns( 1938 f"return {cpp_result};", 1939 ) 1940 1941 def gen_iface_impl_methods_impl( 1942 self, 1943 iface: IfaceDecl, 1944 iface_abi_info: IfaceABIInfo, 1945 iface_cpp_info: IfaceCppInfo, 1946 iface_cpp_impl_target: CHeaderWriter, 1947 ): 1948 iface_cpp_impl_target.writelns( 1949 f"template<typename Impl>", 1950 ) 1951 with iface_cpp_impl_target.indented( 1952 f"struct {iface_cpp_info.full_weak_name}::methods_impl {{", 1953 f"}};", 1954 ): 1955 for method in iface.methods: 1956 method_cpp_info = IfaceMethodCppInfo.get(self.am, method) 1957 params_abi = [f"{iface_abi_info.as_param} tobj"] 1958 args_from_abi = [] 1959 for param in method.params: 1960 type_abi_info = TypeABIInfo.get(self.am, param.ty_ref.resolved_ty) 1961 type_cpp_info = TypeCppInfo.get(self.am, param.ty_ref.resolved_ty) 1962 params_abi.append(f"{type_abi_info.as_param} {param.name}") 1963 args_from_abi.append(type_cpp_info.pass_from_abi(param.name)) 1964 params_abi_str = ", ".join(params_abi) 1965 args_from_abi_str = ", ".join(args_from_abi) 1966 cpp_result = f"::taihe::cast_data_ptr<Impl>(tobj.data_ptr)->{method_cpp_info.impl_name}({args_from_abi_str})" 1967 if return_ty_ref := method.return_ty_ref: 1968 type_abi_info = TypeABIInfo.get(self.am, return_ty_ref.resolved_ty) 1969 type_cpp_info = TypeCppInfo.get(self.am, return_ty_ref.resolved_ty) 1970 abi_return_ty_name = type_abi_info.as_owner 1971 abi_result = type_cpp_info.return_into_abi(cpp_result) 1972 else: 1973 abi_return_ty_name = "void" 1974 abi_result = cpp_result 1975 with iface_cpp_impl_target.indented( 1976 f"static {abi_return_ty_name} {method.name}({params_abi_str}) {{", 1977 f"}}", 1978 ): 1979 iface_cpp_impl_target.writelns( 1980 f"return {abi_result};", 1981 ) 1982 1983 def gen_iface_ftbl_impl( 1984 self, 1985 iface: IfaceDecl, 1986 iface_abi_info: IfaceABIInfo, 1987 iface_cpp_info: IfaceCppInfo, 1988 iface_cpp_impl_target: CHeaderWriter, 1989 ): 1990 iface_cpp_impl_target.writelns( 1991 f"template<typename Impl>", 1992 ) 1993 with iface_cpp_impl_target.indented( 1994 f"constexpr {iface_abi_info.ftable} {iface_cpp_info.weakspace}::{iface_cpp_info.weak_name}::ftbl_impl = {{", 1995 f"}};", 1996 ): 1997 for method in iface.methods: 1998 iface_cpp_impl_target.writelns( 1999 f".{method.name} = &methods_impl<Impl>::{method.name},", 2000 )