• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                )