1 /* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_OBJECT_TYPE_H 17 #define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_OBJECT_TYPE_H 18 19 #include "checker/types/type.h" 20 #include "checker/types/ets/etsObjectTypeConstants.h" 21 #include "checker/types/signature.h" 22 #include "ir/ts/tsInterfaceDeclaration.h" 23 #include "ir/ts/tsTypeParameterDeclaration.h" 24 #include "ir/ts/tsEnumDeclaration.h" 25 #include "varbinder/scope.h" 26 #include "ir/base/classDefinition.h" 27 28 namespace ark::es2panda::checker { 29 using PropertyProcesser = std::function<varbinder::LocalVariable *(varbinder::LocalVariable *, Type *)>; 30 31 inline constexpr auto *PARTIAL_CLASS_SUFFIX = "$partial"; 32 33 class ETSObjectType : public Type { 34 public: 35 using PropertyMap = ArenaUnorderedMap<util::StringView, varbinder::LocalVariable *>; 36 using InstantiationMap = ArenaUnorderedMap<util::StringView, ETSObjectType *>; 37 using PropertyTraverser = std::function<void(const varbinder::LocalVariable *)>; 38 using PropertyHolder = std::array<PropertyMap, static_cast<size_t>(PropertyType::COUNT)>; 39 ETSObjectType(ArenaAllocator * allocator)40 explicit ETSObjectType(ArenaAllocator *allocator) : ETSObjectType(allocator, ETSObjectFlags::NO_OPTS) {} 41 ETSObjectType(ArenaAllocator * allocator,ETSObjectFlags flags)42 explicit ETSObjectType(ArenaAllocator *allocator, ETSObjectFlags flags) 43 : ETSObjectType(allocator, "", "", std::make_tuple(nullptr, flags, nullptr)) 44 { 45 } 46 ETSObjectType(ArenaAllocator * allocator,ETSObjectFlags flags,TypeRelation * relation)47 explicit ETSObjectType(ArenaAllocator *allocator, ETSObjectFlags flags, TypeRelation *relation) 48 : ETSObjectType(allocator, "", "", std::make_tuple(nullptr, flags, relation)) 49 { 50 } 51 ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView assemblerName,ir::AstNode * declNode,ETSObjectFlags flags)52 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, 53 ir::AstNode *declNode, ETSObjectFlags flags) 54 : ETSObjectType(allocator, name, assemblerName, std::make_tuple(declNode, flags, nullptr), 55 std::make_index_sequence<static_cast<size_t>(PropertyType::COUNT)> {}) 56 { 57 } 58 ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView assemblerName,std::tuple<ir::AstNode *,ETSObjectFlags,TypeRelation * > info)59 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, 60 std::tuple<ir::AstNode *, ETSObjectFlags, TypeRelation *> info) 61 : ETSObjectType(allocator, name, assemblerName, info, 62 std::make_index_sequence<static_cast<size_t>(PropertyType::COUNT)> {}) 63 { 64 } 65 AddConstructSignature(Signature * signature)66 void AddConstructSignature(Signature *signature) 67 { 68 constructSignatures_.push_back(signature); 69 propertiesInstantiated_ = true; 70 } 71 AddConstructSignature(const ArenaVector<Signature * > & signatures)72 void AddConstructSignature(const ArenaVector<Signature *> &signatures) const 73 { 74 constructSignatures_.insert(constructSignatures_.end(), signatures.begin(), signatures.end()); 75 propertiesInstantiated_ = true; 76 } 77 AddInterface(ETSObjectType * interface)78 void AddInterface(ETSObjectType *interface) 79 { 80 if (std::find(interfaces_.begin(), interfaces_.end(), interface) == interfaces_.end()) { 81 interfaces_.push_back(interface); 82 } 83 } 84 SetSuperType(ETSObjectType * super)85 void SetSuperType(ETSObjectType *super) 86 { 87 superType_ = super; 88 } 89 SetTypeArguments(ArenaVector<Type * > && typeArgs)90 void SetTypeArguments(ArenaVector<Type *> &&typeArgs) 91 { 92 #ifndef NDEBUG 93 for (auto const &t : typeArgs) { 94 ASSERT(t->IsETSReferenceType()); 95 } 96 #endif 97 typeArguments_ = std::move(typeArgs); 98 } 99 SetEnclosingType(ETSObjectType * enclosingType)100 void SetEnclosingType(ETSObjectType *enclosingType) 101 { 102 enclosingType_ = enclosingType; 103 } 104 SetRelation(TypeRelation * relation)105 void SetRelation(TypeRelation *relation) 106 { 107 relation_ = relation; 108 } 109 GetRelation()110 TypeRelation *GetRelation() const 111 { 112 return relation_; 113 } 114 InstanceMethods()115 PropertyMap InstanceMethods() const 116 { 117 EnsurePropertiesInstantiated(); 118 return properties_[static_cast<size_t>(PropertyType::INSTANCE_METHOD)]; 119 } 120 InstanceFields()121 PropertyMap InstanceFields() const 122 { 123 EnsurePropertiesInstantiated(); 124 return properties_[static_cast<size_t>(PropertyType::INSTANCE_FIELD)]; 125 } 126 InstanceDecls()127 PropertyMap InstanceDecls() const 128 { 129 EnsurePropertiesInstantiated(); 130 return properties_[static_cast<size_t>(PropertyType::INSTANCE_DECL)]; 131 } 132 StaticMethods()133 PropertyMap StaticMethods() const 134 { 135 EnsurePropertiesInstantiated(); 136 return properties_[static_cast<size_t>(PropertyType::STATIC_METHOD)]; 137 } 138 StaticFields()139 PropertyMap StaticFields() const 140 { 141 EnsurePropertiesInstantiated(); 142 return properties_[static_cast<size_t>(PropertyType::STATIC_FIELD)]; 143 } 144 StaticDecls()145 PropertyMap StaticDecls() const 146 { 147 EnsurePropertiesInstantiated(); 148 return properties_[static_cast<size_t>(PropertyType::STATIC_DECL)]; 149 } 150 TypeArguments()151 const ArenaVector<Type *> &TypeArguments() const 152 { 153 return typeArguments_; 154 } 155 ConstructSignatures()156 const ArenaVector<Signature *> &ConstructSignatures() const 157 { 158 EnsurePropertiesInstantiated(); 159 return constructSignatures_; 160 } 161 ConstructSignatures()162 ArenaVector<Signature *> &ConstructSignatures() 163 { 164 EnsurePropertiesInstantiated(); 165 return constructSignatures_; 166 } 167 Interfaces()168 const ArenaVector<ETSObjectType *> &Interfaces() const 169 { 170 return interfaces_; 171 } 172 Interfaces()173 ArenaVector<ETSObjectType *> &Interfaces() 174 { 175 return interfaces_; 176 } 177 GetDeclNode()178 ir::AstNode *GetDeclNode() const 179 { 180 return declNode_; 181 } 182 SuperType()183 const ETSObjectType *SuperType() const 184 { 185 return superType_; 186 } 187 SuperType()188 ETSObjectType *SuperType() 189 { 190 return superType_; 191 } 192 EnclosingType()193 const ETSObjectType *EnclosingType() const 194 { 195 return enclosingType_; 196 } 197 EnclosingType()198 ETSObjectType *EnclosingType() 199 { 200 return enclosingType_; 201 } 202 OutermostClass()203 ETSObjectType *OutermostClass() 204 { 205 auto *iter = enclosingType_; 206 207 while (iter != nullptr && iter->EnclosingType() != nullptr) { 208 iter = iter->EnclosingType(); 209 } 210 211 return iter; 212 } 213 SetBaseType(ETSObjectType * baseType)214 void SetBaseType(ETSObjectType *baseType) 215 { 216 baseType_ = baseType; 217 } 218 GetBaseType()219 ETSObjectType *GetBaseType() noexcept 220 { 221 return baseType_; 222 } 223 GetBaseType()224 const ETSObjectType *GetBaseType() const noexcept 225 { 226 return baseType_; 227 } 228 229 ETSObjectType const *GetConstOriginalBaseType() const noexcept; 230 GetOriginalBaseType()231 ETSObjectType *GetOriginalBaseType() const noexcept 232 { 233 return const_cast<ETSObjectType *>(GetConstOriginalBaseType()); 234 } 235 IsGlobalETSObjectType()236 bool IsGlobalETSObjectType() const noexcept 237 { 238 return superType_ == nullptr; 239 } 240 241 bool IsPropertyInherited(const varbinder::Variable *var); 242 243 bool IsPropertyOfAscendant(const varbinder::Variable *var) const; 244 245 bool IsSignatureInherited(Signature *signature); 246 247 bool IsDescendantOf(const ETSObjectType *ascendant) const; 248 Name()249 const util::StringView &Name() const 250 { 251 return name_; 252 } 253 AssemblerName()254 const util::StringView &AssemblerName() const 255 { 256 return assemblerName_; 257 } 258 SetName(const util::StringView & newName)259 void SetName(const util::StringView &newName) 260 { 261 name_ = newName; 262 } 263 SetAssemblerName(const util::StringView & newName)264 void SetAssemblerName(const util::StringView &newName) 265 { 266 assemblerName_ = newName; 267 } 268 ObjectFlags()269 ETSObjectFlags ObjectFlags() const 270 { 271 return flags_; 272 } 273 AddObjectFlag(ETSObjectFlags flag)274 void AddObjectFlag(ETSObjectFlags flag) 275 { 276 flags_ |= flag; 277 } 278 RemoveObjectFlag(ETSObjectFlags flag)279 void RemoveObjectFlag(ETSObjectFlags flag) 280 { 281 flags_ &= ~flag; 282 } 283 HasObjectFlag(ETSObjectFlags flag)284 bool HasObjectFlag(ETSObjectFlags flag) const 285 { 286 return (flags_ & flag) != 0; 287 } 288 GetFunctionalInterfaceInvokeType()289 ETSFunctionType *GetFunctionalInterfaceInvokeType() const 290 { 291 ASSERT(HasObjectFlag(ETSObjectFlags::FUNCTIONAL)); 292 auto *invoke = GetOwnProperty<PropertyType::INSTANCE_METHOD>(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME); 293 ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType()); 294 return invoke->TsType()->AsETSFunctionType(); 295 } 296 BuiltInKind()297 ETSObjectFlags BuiltInKind() const 298 { 299 return static_cast<checker::ETSObjectFlags>(flags_ & ETSObjectFlags::BUILTIN_TYPE); 300 } 301 UnboxableKind()302 ETSObjectFlags UnboxableKind() const 303 { 304 return static_cast<checker::ETSObjectFlags>(flags_ & ETSObjectFlags::UNBOXABLE_TYPE); 305 } 306 GetUnboxedEnumType()307 ETSEnumType *GetUnboxedEnumType() const 308 { 309 ASSERT(HasObjectFlag(ETSObjectFlags::BOXED_ENUM)); 310 return GetDeclNode()->AsClassDefinition()->OrigEnumDecl()->TsType()->AsETSEnumType(); 311 } 312 GetInstantiatedType(util::StringView hash)313 ETSObjectType *GetInstantiatedType(util::StringView hash) 314 { 315 auto found = instantiationMap_.find(hash); 316 if (found != instantiationMap_.end()) { 317 return found->second; 318 } 319 320 return nullptr; 321 } 322 GetTypeArgumentScope()323 varbinder::Scope *GetTypeArgumentScope() const 324 { 325 auto *typeParams = GetTypeParams(); 326 if (typeParams == nullptr) { 327 return nullptr; 328 } 329 return typeParams->Scope(); 330 } 331 GetInstantiationMap()332 InstantiationMap &GetInstantiationMap() 333 { 334 return instantiationMap_; 335 } 336 337 template <PropertyType TYPE> GetOwnProperty(const util::StringView & name)338 varbinder::LocalVariable *GetOwnProperty(const util::StringView &name) const 339 { 340 EnsurePropertiesInstantiated(); 341 auto found = properties_[static_cast<size_t>(TYPE)].find(name); 342 if (found != properties_[static_cast<size_t>(TYPE)].end()) { 343 return found->second; 344 } 345 return nullptr; 346 } 347 348 template <PropertyType TYPE> AddProperty(varbinder::LocalVariable * prop)349 void AddProperty(varbinder::LocalVariable *prop) const 350 { 351 properties_[static_cast<size_t>(TYPE)].emplace(prop->Name(), prop); 352 propertiesInstantiated_ = true; 353 } 354 355 template <PropertyType TYPE> AddProperty(varbinder::LocalVariable * prop,util::StringView localName)356 void AddProperty(varbinder::LocalVariable *prop, util::StringView localName) const 357 { 358 util::StringView nameToAccess = prop->Name(); 359 360 if (!localName.Empty()) { 361 nameToAccess = localName; 362 } 363 364 properties_[static_cast<size_t>(TYPE)].emplace(nameToAccess, prop); 365 propertiesInstantiated_ = true; 366 } 367 368 template <PropertyType TYPE> RemoveProperty(varbinder::LocalVariable * prop)369 void RemoveProperty(varbinder::LocalVariable *prop) 370 { 371 properties_[static_cast<size_t>(TYPE)].erase(prop->Name()); 372 propertiesInstantiated_ = true; 373 } 374 IsGeneric()375 [[nodiscard]] bool IsGeneric() const noexcept 376 { 377 return !typeArguments_.empty(); 378 } 379 IsPartial()380 [[nodiscard]] bool IsPartial() const noexcept 381 { 382 return name_.EndsWith(PARTIAL_CLASS_SUFFIX); 383 } 384 385 std::vector<const varbinder::LocalVariable *> ForeignProperties() const; 386 varbinder::LocalVariable *GetProperty(const util::StringView &name, PropertySearchFlags flags) const; 387 std::vector<varbinder::LocalVariable *> GetAllProperties() const; 388 void CreatePropertyMap(ArenaAllocator *allocator); 389 varbinder::LocalVariable *CopyProperty(varbinder::LocalVariable *prop, ArenaAllocator *allocator, 390 TypeRelation *relation, GlobalTypesHolder *globalTypes); 391 std::vector<varbinder::LocalVariable *> Methods() const; 392 std::vector<varbinder::LocalVariable *> Fields() const; 393 varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(const util::StringView &name, 394 PropertySearchFlags flags) const; 395 varbinder::LocalVariable *CollectSignaturesForSyntheticType(ETSFunctionType *funcType, const util::StringView &name, 396 PropertySearchFlags flags) const; 397 bool CheckIdenticalFlags(ETSObjectType *other) const; 398 bool CheckIdenticalVariable(varbinder::Variable *otherVar) const; 399 400 void Iterate(const PropertyTraverser &cb) const; 401 void ToString(std::stringstream &ss, bool precise) const override; 402 void Identical(TypeRelation *relation, Type *other) override; 403 bool AssignmentSource(TypeRelation *relation, Type *target) override; 404 void AssignmentTarget(TypeRelation *relation, Type *source) override; 405 Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; 406 void UpdateTypeProperties(checker::ETSChecker *checker, PropertyProcesser const &func); 407 ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution) override; 408 ETSObjectType *Substitute(TypeRelation *relation, const Substitution *substitution, bool cache); 409 ETSObjectType *SubstituteArguments(TypeRelation *relation, ArenaVector<Type *> const &arguments); 410 void Cast(TypeRelation *relation, Type *target) override; 411 bool CastNumericObject(TypeRelation *relation, Type *target); 412 bool DefaultObjectTypeChecks(const ETSChecker *etsChecker, TypeRelation *relation, Type *source); 413 void IsSupertypeOf(TypeRelation *relation, Type *source) override; 414 Type *AsSuper(Checker *checker, varbinder::Variable *sourceVar) override; 415 void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override; 416 static void DebugInfoTypeFromName(std::stringstream &ss, util::StringView asmName); 417 void ToDebugInfoType(std::stringstream &ss) const override; 418 void ToDebugInfoSignatureType(std::stringstream &ss) const; 419 420 void AddReExports(ETSObjectType *reExport); 421 void AddReExportAlias(util::StringView const &value, util::StringView const &key); 422 util::StringView GetReExportAliasValue(util::StringView const &key) const; 423 bool IsReExportHaveAliasValue(util::StringView const &key) const; 424 const ArenaVector<ETSObjectType *> &ReExports() const; 425 Allocator()426 ArenaAllocator *Allocator() const 427 { 428 return allocator_; 429 } 430 ResolveConditionExpr()431 std::tuple<bool, bool> ResolveConditionExpr() const override 432 { 433 return {false, false}; 434 } 435 436 [[nodiscard]] static std::uint32_t GetPrecedence(checker::ETSChecker *checker, ETSObjectType const *type) noexcept; 437 IsPropertiesInstantiated()438 bool IsPropertiesInstantiated() const 439 { 440 return propertiesInstantiated_; 441 } 442 443 protected: 444 virtual ETSFunctionType *CreateETSFunctionType(const util::StringView &name) const; 445 446 private: 447 template <size_t... IS> ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView assemblerName,std::tuple<ir::AstNode *,ETSObjectFlags,TypeRelation * > info,std::index_sequence<IS...> s)448 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, 449 std::tuple<ir::AstNode *, ETSObjectFlags, TypeRelation *> info, 450 [[maybe_unused]] std::index_sequence<IS...> s) 451 : Type(TypeFlag::ETS_OBJECT), 452 allocator_(allocator), 453 name_(name), 454 assemblerName_(assemblerName), 455 declNode_(std::get<ir::AstNode *>(info)), 456 interfaces_(allocator->Adapter()), 457 reExports_(allocator->Adapter()), 458 reExportAlias_(allocator->Adapter()), 459 flags_(std::get<ETSObjectFlags>(info)), 460 instantiationMap_(allocator->Adapter()), 461 typeArguments_(allocator->Adapter()), 462 relation_(std::get<TypeRelation *>(info)), 463 constructSignatures_(allocator->Adapter()), 464 properties_ {(void(IS), PropertyMap {allocator->Adapter()})...} 465 { 466 } 467 468 /* Properties and construct signatures are instantiated lazily. */ 469 void InstantiateProperties() const; EnsurePropertiesInstantiated()470 void EnsurePropertiesInstantiated() const 471 { 472 if (!propertiesInstantiated_) { 473 InstantiateProperties(); 474 propertiesInstantiated_ = true; 475 } 476 } 477 ArenaMap<util::StringView, const varbinder::LocalVariable *> CollectAllProperties() const; 478 bool CastWideningNarrowing(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags, 479 TypeFlag narrowingFlags); 480 void IdenticalUptoTypeArguments(TypeRelation *relation, Type *other); 481 void SubstitutePartialTypes(TypeRelation *relation, Type *other); 482 void IsGenericSupertypeOf(TypeRelation *relation, Type *source); 483 void UpdateTypeProperty(checker::ETSChecker *checker, varbinder::LocalVariable *const prop, PropertyType fieldType, 484 PropertyProcesser const &func); 485 486 varbinder::LocalVariable *SearchFieldsDecls(const util::StringView &name, PropertySearchFlags flags) const; 487 488 void SetCopiedTypeProperties(TypeRelation *relation, ETSObjectType *copiedType, ArenaVector<Type *> &&newTypeArgs, 489 ETSObjectType *base); 490 bool SubstituteTypeArgs(TypeRelation *relation, ArenaVector<Type *> &newTypeArgs, const Substitution *substitution); 491 492 bool TryCastByte(TypeRelation *const relation, Type *const target); 493 bool TryCastIntegral(TypeRelation *const relation, Type *const target); 494 bool TryCastFloating(TypeRelation *const relation, Type *const target); 495 bool TryCastUnboxable(TypeRelation *const relation, Type *const target); 496 497 ir::TSTypeParameterDeclaration *GetTypeParams() const; 498 499 ArenaAllocator *allocator_; 500 util::StringView name_; 501 util::StringView assemblerName_; 502 ir::AstNode *declNode_; 503 ArenaVector<ETSObjectType *> interfaces_; 504 ArenaVector<ETSObjectType *> reExports_; 505 ArenaMap<util::StringView, util::StringView> reExportAlias_; 506 ETSObjectFlags flags_; 507 InstantiationMap instantiationMap_; 508 ArenaVector<Type *> typeArguments_; 509 ETSObjectType *superType_ {}; 510 ETSObjectType *enclosingType_ {}; 511 ETSObjectType *baseType_ {}; 512 513 // for lazy properties instantiation 514 TypeRelation *relation_ = nullptr; 515 const Substitution *effectiveSubstitution_ = nullptr; 516 mutable bool propertiesInstantiated_ = false; 517 mutable ArenaVector<Signature *> constructSignatures_; 518 mutable PropertyHolder properties_; 519 }; 520 } // namespace ark::es2panda::checker 521 522 #endif /* TYPESCRIPT_TYPES_FUNCTION_TYPE_H */ 523