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 abc import ABCMeta 17 18from typing_extensions import override 19 20from taihe.semantics.declarations import ( 21 EnumDecl, 22 GlobFuncDecl, 23 IfaceDecl, 24 IfaceMethodDecl, 25 PackageDecl, 26 StructDecl, 27 UnionDecl, 28) 29from taihe.semantics.types import ( 30 ArrayType, 31 CallbackType, 32 EnumType, 33 IfaceType, 34 MapType, 35 OpaqueType, 36 OptionalType, 37 ScalarKind, 38 ScalarType, 39 SetType, 40 StringType, 41 StructType, 42 Type, 43 UnionType, 44 VectorType, 45) 46from taihe.semantics.visitor import TypeVisitor 47from taihe.utils.analyses import AbstractAnalysis, AnalysisManager 48 49 50class PackageCppInfo(AbstractAnalysis[PackageDecl]): 51 def __init__(self, am: AnalysisManager, p: PackageDecl) -> None: 52 super().__init__(am, p) 53 self.header = f"{p.name}.proj.hpp" 54 55 56class IfaceMethodCppInfo(AbstractAnalysis[IfaceMethodDecl]): 57 def __init__(self, am: AnalysisManager, f: IfaceMethodDecl) -> None: 58 super().__init__(am, f) 59 self.call_name = f.name 60 self.impl_name = f.name 61 62 63class EnumCppInfo(AbstractAnalysis[EnumDecl]): 64 def __init__(self, am: AnalysisManager, d: EnumDecl) -> None: 65 super().__init__(am, d) 66 self.decl_header = f"{d.parent_pkg.name}.{d.name}.proj.0.hpp" 67 self.defn_header = f"{d.parent_pkg.name}.{d.name}.proj.1.hpp" 68 69 self.namespace = "::".join(d.parent_pkg.segments) 70 self.name = d.name 71 self.full_name = "::" + self.namespace + "::" + self.name 72 73 self.as_owner = self.full_name 74 self.as_param = self.full_name 75 76 77class StructCppInfo(AbstractAnalysis[StructDecl]): 78 def __init__(self, am: AnalysisManager, d: StructDecl) -> None: 79 super().__init__(am, d) 80 self.decl_header = f"{d.parent_pkg.name}.{d.name}.proj.0.hpp" 81 self.defn_header = f"{d.parent_pkg.name}.{d.name}.proj.1.hpp" 82 self.impl_header = f"{d.parent_pkg.name}.{d.name}.proj.2.hpp" 83 84 self.namespace = "::".join(d.parent_pkg.segments) 85 self.name = d.name 86 self.full_name = "::" + self.namespace + "::" + self.name 87 88 self.as_owner = self.full_name 89 self.as_param = self.full_name + " const&" 90 91 92class UnionCppInfo(AbstractAnalysis[UnionDecl]): 93 def __init__(self, am: AnalysisManager, d: UnionDecl) -> None: 94 super().__init__(am, d) 95 self.decl_header = f"{d.parent_pkg.name}.{d.name}.proj.0.hpp" 96 self.defn_header = f"{d.parent_pkg.name}.{d.name}.proj.1.hpp" 97 self.impl_header = f"{d.parent_pkg.name}.{d.name}.proj.2.hpp" 98 99 self.namespace = "::".join(d.parent_pkg.segments) 100 self.name = d.name 101 self.full_name = "::" + self.namespace + "::" + self.name 102 103 self.as_owner = self.full_name 104 self.as_param = self.full_name + " const&" 105 106 107class IfaceCppInfo(AbstractAnalysis[IfaceDecl]): 108 def __init__(self, am: AnalysisManager, d: IfaceDecl) -> None: 109 super().__init__(am, d) 110 self.decl_header = f"{d.parent_pkg.name}.{d.name}.proj.0.hpp" 111 self.defn_header = f"{d.parent_pkg.name}.{d.name}.proj.1.hpp" 112 self.impl_header = f"{d.parent_pkg.name}.{d.name}.proj.2.hpp" 113 114 self.namespace = "::".join(d.parent_pkg.segments) 115 self.norm_name = d.name 116 self.full_norm_name = "::" + self.namespace + "::" + self.norm_name 117 118 self.weakspace = "::".join(d.parent_pkg.segments) + "::weak" 119 self.weak_name = d.name 120 self.full_weak_name = "::" + self.weakspace + "::" + self.weak_name 121 122 self.as_owner = self.full_norm_name 123 self.as_param = self.full_weak_name 124 125 126class AbstractTypeCppInfo(metaclass=ABCMeta): 127 decl_headers: list[str] 128 defn_headers: list[str] 129 impl_headers: list[str] 130 as_owner: str 131 as_param: str 132 133 def return_from_abi(self, val): 134 return f"::taihe::from_abi<{self.as_owner}>({val})" 135 136 def return_into_abi(self, val): 137 return f"::taihe::into_abi<{self.as_owner}>({val})" 138 139 def pass_from_abi(self, val): 140 return f"::taihe::from_abi<{self.as_param}>({val})" 141 142 def pass_into_abi(self, val): 143 return f"::taihe::into_abi<{self.as_param}>({val})" 144 145 146class EnumTypeCppInfo(AbstractAnalysis[EnumType], AbstractTypeCppInfo): 147 def __init__(self, am: AnalysisManager, t: EnumType): 148 super().__init__(am, t) 149 enum_cpp_info = EnumCppInfo.get(am, t.ty_decl) 150 self.decl_headers = [enum_cpp_info.decl_header] 151 self.defn_headers = [enum_cpp_info.defn_header] 152 self.impl_headers = [enum_cpp_info.defn_header] 153 self.as_owner = enum_cpp_info.as_owner 154 self.as_param = enum_cpp_info.as_param 155 156 157class UnionTypeCppInfo(AbstractAnalysis[UnionType], AbstractTypeCppInfo): 158 def __init__(self, am: AnalysisManager, t: UnionType): 159 super().__init__(am, t) 160 union_cpp_info = UnionCppInfo.get(am, t.ty_decl) 161 self.decl_headers = [union_cpp_info.decl_header] 162 self.defn_headers = [union_cpp_info.defn_header] 163 self.impl_headers = [union_cpp_info.impl_header] 164 self.as_owner = union_cpp_info.as_owner 165 self.as_param = union_cpp_info.as_param 166 167 168class StructTypeCppInfo(AbstractAnalysis[StructType], AbstractTypeCppInfo): 169 def __init__(self, am: AnalysisManager, t: StructType): 170 super().__init__(am, t) 171 struct_cpp_info = StructCppInfo.get(am, t.ty_decl) 172 self.decl_headers = [struct_cpp_info.decl_header] 173 self.defn_headers = [struct_cpp_info.defn_header] 174 self.impl_headers = [struct_cpp_info.impl_header] 175 self.as_owner = struct_cpp_info.as_owner 176 self.as_param = struct_cpp_info.as_param 177 178 179class IfaceTypeCppInfo(AbstractAnalysis[IfaceType], AbstractTypeCppInfo): 180 def __init__(self, am: AnalysisManager, t: IfaceType): 181 super().__init__(am, t) 182 iface_cpp_info = IfaceCppInfo.get(am, t.ty_decl) 183 self.decl_headers = [iface_cpp_info.decl_header] 184 self.defn_headers = [iface_cpp_info.defn_header] 185 self.impl_headers = [iface_cpp_info.impl_header] 186 self.as_owner = iface_cpp_info.as_owner 187 self.as_param = iface_cpp_info.as_param 188 189 190class ScalarTypeCppInfo(AbstractAnalysis[ScalarType], AbstractTypeCppInfo): 191 def __init__(self, am: AnalysisManager, t: ScalarType): 192 super().__init__(am, t) 193 res = { 194 ScalarKind.BOOL: "bool", 195 ScalarKind.F32: "float", 196 ScalarKind.F64: "double", 197 ScalarKind.I8: "int8_t", 198 ScalarKind.I16: "int16_t", 199 ScalarKind.I32: "int32_t", 200 ScalarKind.I64: "int64_t", 201 ScalarKind.U8: "uint8_t", 202 ScalarKind.U16: "uint16_t", 203 ScalarKind.U32: "uint32_t", 204 ScalarKind.U64: "uint64_t", 205 }.get(t.kind) 206 if res is None: 207 raise ValueError 208 self.decl_headers = [] 209 self.defn_headers = [] 210 self.impl_headers = [] 211 self.as_param = res 212 self.as_owner = res 213 214 215class OpaqueTypeCppInfo(AbstractAnalysis[OpaqueType], AbstractTypeCppInfo): 216 def __init__(self, am: AnalysisManager, t: OpaqueType) -> None: 217 super().__init__(am, t) 218 self.decl_headers = [] 219 self.defn_headers = [] 220 self.impl_headers = [] 221 self.as_param = "uintptr_t" 222 self.as_owner = "uintptr_t" 223 224 225class StringTypeCppInfo(AbstractAnalysis[StringType], AbstractTypeCppInfo): 226 def __init__(self, am: AnalysisManager, t: StringType): 227 super().__init__(am, t) 228 self.decl_headers = ["taihe/string.hpp"] 229 self.defn_headers = ["taihe/string.hpp"] 230 self.impl_headers = ["taihe/string.hpp"] 231 self.as_owner = "::taihe::string" 232 self.as_param = "::taihe::string_view" 233 234 235class ArrayTypeCppInfo(AbstractAnalysis[ArrayType], AbstractTypeCppInfo): 236 def __init__(self, am: AnalysisManager, t: ArrayType) -> None: 237 super().__init__(am, t) 238 arg_ty_cpp_info = TypeCppInfo.get(am, t.item_ty) 239 self.decl_headers = ["taihe/array.hpp", *arg_ty_cpp_info.decl_headers] 240 self.defn_headers = ["taihe/array.hpp", *arg_ty_cpp_info.decl_headers] 241 self.impl_headers = ["taihe/array.hpp", *arg_ty_cpp_info.impl_headers] 242 self.as_owner = f"::taihe::array<{arg_ty_cpp_info.as_owner}>" 243 self.as_param = f"::taihe::array_view<{arg_ty_cpp_info.as_owner}>" 244 245 246class OptionalTypeCppInfo(AbstractAnalysis[OptionalType], AbstractTypeCppInfo): 247 def __init__(self, am: AnalysisManager, t: OptionalType) -> None: 248 super().__init__(am, t) 249 arg_ty_cpp_info = TypeCppInfo.get(am, t.item_ty) 250 self.decl_headers = ["taihe/optional.hpp", *arg_ty_cpp_info.decl_headers] 251 self.defn_headers = ["taihe/optional.hpp", *arg_ty_cpp_info.decl_headers] 252 self.impl_headers = ["taihe/optional.hpp", *arg_ty_cpp_info.impl_headers] 253 self.as_owner = f"::taihe::optional<{arg_ty_cpp_info.as_owner}>" 254 self.as_param = f"::taihe::optional_view<{arg_ty_cpp_info.as_owner}>" 255 256 257class VectorTypeCppInfo(AbstractAnalysis[VectorType], AbstractTypeCppInfo): 258 def __init__(self, am: AnalysisManager, t: VectorType) -> None: 259 super().__init__(am, t) 260 val_ty_cpp_info = TypeCppInfo.get(am, t.val_ty) 261 self.decl_headers = ["taihe/vector.hpp", *val_ty_cpp_info.decl_headers] 262 self.defn_headers = ["taihe/vector.hpp", *val_ty_cpp_info.decl_headers] 263 self.impl_headers = ["taihe/vector.hpp", *val_ty_cpp_info.impl_headers] 264 self.as_owner = f"::taihe::vector<{val_ty_cpp_info.as_owner}>" 265 self.as_param = f"::taihe::vector_view<{val_ty_cpp_info.as_owner}>" 266 267 268class MapTypeCppInfo(AbstractAnalysis[MapType], AbstractTypeCppInfo): 269 def __init__(self, am: AnalysisManager, t: MapType) -> None: 270 super().__init__(am, t) 271 key_ty_cpp_info = TypeCppInfo.get(am, t.key_ty) 272 val_ty_cpp_info = TypeCppInfo.get(am, t.val_ty) 273 self.decl_headers = [ 274 "taihe/map.hpp", 275 *key_ty_cpp_info.decl_headers, 276 *val_ty_cpp_info.decl_headers, 277 ] 278 self.defn_headers = [ 279 "taihe/map.hpp", 280 *key_ty_cpp_info.decl_headers, 281 *val_ty_cpp_info.decl_headers, 282 ] 283 self.impl_headers = [ 284 "taihe/map.hpp", 285 *key_ty_cpp_info.impl_headers, 286 *val_ty_cpp_info.impl_headers, 287 ] 288 self.as_owner = ( 289 f"::taihe::map<{key_ty_cpp_info.as_owner}, {val_ty_cpp_info.as_owner}>" 290 ) 291 self.as_param = ( 292 f"::taihe::map_view<{key_ty_cpp_info.as_owner}, {val_ty_cpp_info.as_owner}>" 293 ) 294 295 296class SetTypeCppInfo(AbstractAnalysis[SetType], AbstractTypeCppInfo): 297 def __init__(self, am: AnalysisManager, t: SetType) -> None: 298 super().__init__(am, t) 299 key_ty_cpp_info = TypeCppInfo.get(am, t.key_ty) 300 self.decl_headers = ["taihe/set.hpp", *key_ty_cpp_info.decl_headers] 301 self.defn_headers = ["taihe/set.hpp", *key_ty_cpp_info.decl_headers] 302 self.impl_headers = ["taihe/set.hpp", *key_ty_cpp_info.impl_headers] 303 self.as_owner = f"::taihe::set<{key_ty_cpp_info.as_owner}>" 304 self.as_param = f"::taihe::set_view<{key_ty_cpp_info.as_owner}>" 305 306 307class CallbackTypeCppInfo(AbstractAnalysis[CallbackType], AbstractTypeCppInfo): 308 def __init__(self, am: AnalysisManager, t: CallbackType) -> None: 309 super().__init__(am, t) 310 if return_ty := t.return_ty: 311 return_ty_cpp_info = TypeCppInfo.get(am, return_ty) 312 return_ty_decl_headers = return_ty_cpp_info.decl_headers 313 return_ty_impl_headers = return_ty_cpp_info.impl_headers 314 return_ty_as_owner = return_ty_cpp_info.as_owner 315 else: 316 return_ty_decl_headers = [] 317 return_ty_impl_headers = [] 318 return_ty_as_owner = "void" 319 params_ty_decl_headers = [] 320 params_ty_impl_headers = [] 321 params_ty_as_param = [] 322 for param_ty in t.params_ty: 323 param_ty_cpp_info = TypeCppInfo.get(am, param_ty) 324 params_ty_decl_headers.extend(param_ty_cpp_info.decl_headers) 325 params_ty_impl_headers.extend(param_ty_cpp_info.impl_headers) 326 params_ty_as_param.append(param_ty_cpp_info.as_param) 327 params_fmt = ", ".join(params_ty_as_param) 328 self.decl_headers = [ 329 "taihe/callback.hpp", 330 *return_ty_decl_headers, 331 *params_ty_decl_headers, 332 ] 333 self.defn_headers = [ 334 "taihe/callback.hpp", 335 *return_ty_decl_headers, 336 *params_ty_decl_headers, 337 ] 338 self.impl_headers = [ 339 "taihe/callback.hpp", 340 *return_ty_impl_headers, 341 *params_ty_impl_headers, 342 ] 343 self.as_owner = f"::taihe::callback<{return_ty_as_owner}({params_fmt})>" 344 self.as_param = f"::taihe::callback_view<{return_ty_as_owner}({params_fmt})>" 345 346 347class TypeCppInfo(TypeVisitor[AbstractTypeCppInfo]): 348 def __init__(self, am: AnalysisManager): 349 self.am = am 350 351 @staticmethod 352 def get(am: AnalysisManager, t: Type) -> AbstractTypeCppInfo: 353 return TypeCppInfo(am).handle_type(t) 354 355 @override 356 def visit_enum_type(self, t: EnumType) -> AbstractTypeCppInfo: 357 return EnumTypeCppInfo.get(self.am, t) 358 359 @override 360 def visit_union_type(self, t: UnionType) -> AbstractTypeCppInfo: 361 return UnionTypeCppInfo.get(self.am, t) 362 363 @override 364 def visit_struct_type(self, t: StructType) -> AbstractTypeCppInfo: 365 return StructTypeCppInfo.get(self.am, t) 366 367 @override 368 def visit_iface_type(self, t: IfaceType) -> AbstractTypeCppInfo: 369 return IfaceTypeCppInfo.get(self.am, t) 370 371 @override 372 def visit_scalar_type(self, t: ScalarType) -> AbstractTypeCppInfo: 373 return ScalarTypeCppInfo.get(self.am, t) 374 375 @override 376 def visit_opaque_type(self, t: OpaqueType) -> AbstractTypeCppInfo: 377 return OpaqueTypeCppInfo.get(self.am, t) 378 379 @override 380 def visit_string_type(self, t: StringType) -> AbstractTypeCppInfo: 381 return StringTypeCppInfo.get(self.am, t) 382 383 @override 384 def visit_array_type(self, t: ArrayType) -> AbstractTypeCppInfo: 385 return ArrayTypeCppInfo.get(self.am, t) 386 387 @override 388 def visit_optional_type(self, t: OptionalType) -> AbstractTypeCppInfo: 389 return OptionalTypeCppInfo.get(self.am, t) 390 391 @override 392 def visit_vector_type(self, t: VectorType) -> AbstractTypeCppInfo: 393 return VectorTypeCppInfo.get(self.am, t) 394 395 @override 396 def visit_map_type(self, t: MapType) -> AbstractTypeCppInfo: 397 return MapTypeCppInfo.get(self.am, t) 398 399 @override 400 def visit_set_type(self, t: SetType) -> AbstractTypeCppInfo: 401 return SetTypeCppInfo.get(self.am, t) 402 403 @override 404 def visit_callback_type(self, t: CallbackType) -> AbstractTypeCppInfo: 405 return CallbackTypeCppInfo.get(self.am, t) 406 407 408class PackageCppUserInfo(AbstractAnalysis[PackageDecl]): 409 def __init__(self, am: AnalysisManager, p: PackageDecl) -> None: 410 super().__init__(am, p) 411 self.header = f"{p.name}.user.hpp" 412 413 414class GlobFuncCppUserInfo(AbstractAnalysis[GlobFuncDecl]): 415 def __init__(self, am: AnalysisManager, f: GlobFuncDecl) -> None: 416 super().__init__(am, f) 417 self.namespace = "::".join(f.parent_pkg.segments) 418 self.call_name = f.name 419 self.full_name = "::" + self.namespace + "::" + self.call_name