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/signature.h" 21 #include "ir/ts/tsInterfaceDeclaration.h" 22 #include "ir/ts/tsTypeParameterDeclaration.h" 23 #include "varbinder/scope.h" 24 #include "ir/base/classDefinition.h" 25 26 namespace panda::es2panda::checker { 27 28 enum class ETSObjectFlags : uint32_t { 29 NO_OPTS = 0U, 30 CLASS = 1U << 0U, 31 INTERFACE = 1U << 1U, 32 INSTANCE = 1U << 2U, 33 ABSTRACT = 1U << 3U, 34 GLOBAL = 1U << 4U, 35 ENUM = 1U << 5U, 36 FUNCTIONAL = 1U << 6U, 37 RESOLVED_MEMBERS = 1U << 7U, 38 RESOLVED_INTERFACES = 1U << 8U, 39 RESOLVED_SUPER = 1U << 9U, 40 RESOLVED_TYPE_PARAMS = 1U << 10U, 41 CHECKED_COMPATIBLE_ABSTRACTS = 1U << 11U, 42 NULL_TYPE = 1U << 12U, 43 STRING = 1U << 13U, 44 INCOMPLETE_INSTANTIATION = 1U << 14U, 45 INNER = 1U << 15U, 46 DYNAMIC = 1U << 16U, 47 ASYNC_FUNC_RETURN_TYPE = 1U << 17U, 48 CHECKED_INVOKE_LEGITIMACY = 1U << 18U, 49 UNDEFINED_TYPE = 1U << 19U, 50 51 BUILTIN_BIGINT = 1U << 22U, 52 BUILTIN_STRING = 1U << 23U, 53 BUILTIN_BOOLEAN = 1U << 24U, 54 BUILTIN_BYTE = 1U << 25U, 55 BUILTIN_CHAR = 1U << 26U, 56 BUILTIN_SHORT = 1U << 27U, 57 BUILTIN_INT = 1U << 28U, 58 BUILTIN_LONG = 1U << 29U, 59 BUILTIN_FLOAT = 1U << 30U, 60 BUILTIN_DOUBLE = 1U << 31U, 61 62 UNBOXABLE_TYPE = BUILTIN_BOOLEAN | BUILTIN_BYTE | BUILTIN_CHAR | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG | 63 BUILTIN_FLOAT | BUILTIN_DOUBLE, 64 BUILTIN_TYPE = BUILTIN_STRING | BUILTIN_BIGINT | UNBOXABLE_TYPE, 65 VALID_SWITCH_TYPE = 66 BUILTIN_BYTE | BUILTIN_CHAR | BUILTIN_SHORT | BUILTIN_INT | BUILTIN_LONG | BUILTIN_STRING | ENUM, 67 GLOBAL_CLASS = CLASS | GLOBAL, 68 FUNCTIONAL_INTERFACE = INTERFACE | ABSTRACT | FUNCTIONAL, 69 COMPLETELY_RESOLVED = RESOLVED_MEMBERS | RESOLVED_INTERFACES | RESOLVED_SUPER | RESOLVED_TYPE_PARAMS, 70 }; 71 72 DEFINE_BITOPS(ETSObjectFlags) 73 74 // NOTE: Do not change the order of the first 7 flags (including NO_OPTS)! 75 // Because ETSChecker::ValidateResolvedProperty relies on the order of the flags. 76 enum class PropertySearchFlags : uint32_t { 77 NO_OPTS = 0, 78 SEARCH_INSTANCE_METHOD = 1U << 0U, 79 SEARCH_INSTANCE_FIELD = 1U << 1U, 80 SEARCH_INSTANCE_DECL = 1U << 2U, 81 SEARCH_STATIC_METHOD = 1U << 3U, 82 SEARCH_STATIC_FIELD = 1U << 4U, 83 SEARCH_STATIC_DECL = 1U << 5U, 84 85 SEARCH_IN_BASE = 1U << 6U, 86 SEARCH_IN_INTERFACES = 1U << 7U, 87 IGNORE_ABSTRACT = 1U << 8U, 88 ALLOW_FUNCTIONAL_INTERFACE = 1U << 9U, 89 DISALLOW_SYNTHETIC_METHOD_CREATION = 1U << 10U, 90 IS_FUNCTIONAL = 1U << 11U, 91 IS_SETTER = 1U << 12U, 92 IS_GETTER = 1U << 13U, 93 94 SEARCH_INSTANCE = SEARCH_INSTANCE_FIELD | SEARCH_INSTANCE_METHOD | SEARCH_INSTANCE_DECL, 95 SEARCH_STATIC = SEARCH_STATIC_FIELD | SEARCH_STATIC_METHOD | SEARCH_STATIC_DECL, 96 97 SEARCH_METHOD = SEARCH_INSTANCE_METHOD | SEARCH_STATIC_METHOD, 98 SEARCH_FIELD = SEARCH_INSTANCE_FIELD | SEARCH_STATIC_FIELD, 99 SEARCH_DECL = SEARCH_INSTANCE_DECL | SEARCH_STATIC_DECL, 100 SEARCH_ALL = SEARCH_METHOD | SEARCH_FIELD | SEARCH_DECL, 101 }; 102 103 DEFINE_BITOPS(PropertySearchFlags) 104 105 enum class PropertyType { 106 INSTANCE_METHOD, 107 INSTANCE_FIELD, 108 INSTANCE_DECL, 109 STATIC_METHOD, 110 STATIC_FIELD, 111 STATIC_DECL, 112 COUNT, 113 }; 114 115 class ETSObjectType : public Type { 116 public: 117 using PropertyMap = ArenaUnorderedMap<util::StringView, varbinder::LocalVariable *>; 118 using InstantiationMap = ArenaUnorderedMap<util::StringView, ETSObjectType *>; 119 using PropertyTraverser = std::function<void(const varbinder::LocalVariable *)>; 120 using PropertyHolder = std::array<PropertyMap, static_cast<size_t>(PropertyType::COUNT)>; 121 ETSObjectType(ArenaAllocator * allocator)122 explicit ETSObjectType(ArenaAllocator *allocator) : ETSObjectType(allocator, ETSObjectFlags::NO_OPTS) {} 123 ETSObjectType(ArenaAllocator * allocator,ETSObjectFlags flags)124 explicit ETSObjectType(ArenaAllocator *allocator, ETSObjectFlags flags) 125 : ETSObjectType(allocator, "", "", nullptr, flags) 126 { 127 } 128 ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView assemblerName,ir::AstNode * declNode,ETSObjectFlags flags)129 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, 130 ir::AstNode *declNode, ETSObjectFlags flags) 131 : ETSObjectType(allocator, name, assemblerName, declNode, flags, 132 std::make_index_sequence<static_cast<size_t>(PropertyType::COUNT)> {}) 133 { 134 } 135 AddConstructSignature(Signature * signature)136 void AddConstructSignature(Signature *signature) 137 { 138 constructSignatures_.push_back(signature); 139 propertiesInstantiated_ = true; 140 } 141 AddConstructSignature(const ArenaVector<Signature * > & signatures)142 void AddConstructSignature(const ArenaVector<Signature *> &signatures) 143 { 144 constructSignatures_.insert(constructSignatures_.end(), signatures.begin(), signatures.end()); 145 propertiesInstantiated_ = true; 146 } 147 AddInterface(ETSObjectType * interface)148 void AddInterface(ETSObjectType *interface) 149 { 150 if (std::find(interfaces_.begin(), interfaces_.end(), interface) == interfaces_.end()) { 151 interfaces_.push_back(interface); 152 } 153 } 154 SetSuperType(ETSObjectType * super)155 void SetSuperType(ETSObjectType *super) 156 { 157 superType_ = super; 158 } 159 SetTypeArguments(ArenaVector<Type * > && typeArgs)160 void SetTypeArguments(ArenaVector<Type *> &&typeArgs) 161 { 162 typeArguments_ = std::move(typeArgs); 163 } 164 SetEnclosingType(ETSObjectType * enclosingType)165 void SetEnclosingType(ETSObjectType *enclosingType) 166 { 167 enclosingType_ = enclosingType; 168 } 169 InstanceMethods()170 PropertyMap InstanceMethods() const 171 { 172 EnsurePropertiesInstantiated(); 173 return properties_[static_cast<size_t>(PropertyType::INSTANCE_METHOD)]; 174 } 175 InstanceFields()176 PropertyMap InstanceFields() const 177 { 178 EnsurePropertiesInstantiated(); 179 return properties_[static_cast<size_t>(PropertyType::INSTANCE_FIELD)]; 180 } 181 InstanceDecls()182 PropertyMap InstanceDecls() const 183 { 184 EnsurePropertiesInstantiated(); 185 return properties_[static_cast<size_t>(PropertyType::INSTANCE_DECL)]; 186 } 187 StaticMethods()188 PropertyMap StaticMethods() const 189 { 190 EnsurePropertiesInstantiated(); 191 return properties_[static_cast<size_t>(PropertyType::STATIC_METHOD)]; 192 } 193 StaticFields()194 PropertyMap StaticFields() const 195 { 196 EnsurePropertiesInstantiated(); 197 return properties_[static_cast<size_t>(PropertyType::STATIC_FIELD)]; 198 } 199 StaticDecls()200 PropertyMap StaticDecls() const 201 { 202 EnsurePropertiesInstantiated(); 203 return properties_[static_cast<size_t>(PropertyType::STATIC_DECL)]; 204 } 205 TypeArguments()206 const ArenaVector<Type *> &TypeArguments() const 207 { 208 return typeArguments_; 209 } 210 TypeArguments()211 ArenaVector<Type *> &TypeArguments() 212 { 213 return typeArguments_; 214 } 215 ConstructSignatures()216 const ArenaVector<Signature *> &ConstructSignatures() const 217 { 218 EnsurePropertiesInstantiated(); 219 return constructSignatures_; 220 } 221 ConstructSignatures()222 ArenaVector<Signature *> &ConstructSignatures() 223 { 224 EnsurePropertiesInstantiated(); 225 return constructSignatures_; 226 } 227 Interfaces()228 const ArenaVector<ETSObjectType *> &Interfaces() const 229 { 230 return interfaces_; 231 } 232 Interfaces()233 ArenaVector<ETSObjectType *> &Interfaces() 234 { 235 return interfaces_; 236 } 237 GetDeclNode()238 ir::AstNode *GetDeclNode() const 239 { 240 return declNode_; 241 } 242 SuperType()243 const ETSObjectType *SuperType() const 244 { 245 return superType_; 246 } 247 SuperType()248 ETSObjectType *SuperType() 249 { 250 return superType_; 251 } 252 EnclosingType()253 const ETSObjectType *EnclosingType() const 254 { 255 return enclosingType_; 256 } 257 EnclosingType()258 ETSObjectType *EnclosingType() 259 { 260 return enclosingType_; 261 } 262 OutermostClass()263 ETSObjectType *OutermostClass() 264 { 265 auto *iter = enclosingType_; 266 267 while (iter != nullptr && iter->EnclosingType() != nullptr) { 268 iter = iter->EnclosingType(); 269 } 270 271 return iter; 272 } 273 SetBaseType(ETSObjectType * baseType)274 void SetBaseType(ETSObjectType *baseType) 275 { 276 baseType_ = baseType; 277 } 278 GetBaseType()279 ETSObjectType *GetBaseType() noexcept 280 { 281 return baseType_; 282 } 283 GetBaseType()284 const ETSObjectType *GetBaseType() const noexcept 285 { 286 return baseType_; 287 } 288 289 ETSObjectType const *GetConstOriginalBaseType() const noexcept; 290 GetOriginalBaseType()291 ETSObjectType *GetOriginalBaseType() noexcept 292 { 293 return const_cast<ETSObjectType *>(GetConstOriginalBaseType()); 294 } 295 IsPropertyInherited(const varbinder::Variable * var)296 bool IsPropertyInherited(const varbinder::Variable *var) 297 { 298 if (var->HasFlag(varbinder::VariableFlags::PRIVATE)) { 299 return GetProperty(var->Name(), PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL) == 300 var; 301 } 302 303 if (var->HasFlag(varbinder::VariableFlags::PROTECTED)) { 304 return (GetProperty(var->Name(), PropertySearchFlags::SEARCH_FIELD | PropertySearchFlags::SEARCH_DECL) == 305 var) || 306 this->IsPropertyOfAscendant(var); 307 } 308 309 return true; 310 } 311 IsPropertyOfAscendant(const varbinder::Variable * var)312 bool IsPropertyOfAscendant(const varbinder::Variable *var) 313 { 314 if (this->SuperType() == nullptr) { 315 return false; 316 } 317 318 if (this->SuperType()->GetProperty(var->Name(), PropertySearchFlags::SEARCH_FIELD | 319 PropertySearchFlags::SEARCH_DECL) == var) { 320 return true; 321 } 322 323 return this->SuperType()->IsPropertyOfAscendant(var); 324 } 325 IsSignatureInherited(Signature * signature)326 bool IsSignatureInherited(Signature *signature) 327 { 328 if (signature->HasSignatureFlag(SignatureFlags::PRIVATE)) { 329 return signature->Owner() == this; 330 } 331 332 if (signature->HasSignatureFlag(SignatureFlags::PROTECTED)) { 333 return signature->Owner() == this || this->IsDescendantOf(signature->Owner()); 334 } 335 336 return true; 337 } 338 IsDescendantOf(const ETSObjectType * ascendant)339 bool IsDescendantOf(const ETSObjectType *ascendant) 340 { 341 if (this->SuperType() == nullptr) { 342 return false; 343 } 344 345 if (this->SuperType() == ascendant) { 346 return true; 347 } 348 349 return this->SuperType()->IsDescendantOf(ascendant); 350 } 351 Name()352 const util::StringView &Name() const 353 { 354 return name_; 355 } 356 AssemblerName()357 const util::StringView &AssemblerName() const 358 { 359 return assemblerName_; 360 } 361 SetName(const util::StringView & newName)362 void SetName(const util::StringView &newName) 363 { 364 name_ = newName; 365 } 366 SetAssemblerName(const util::StringView & newName)367 void SetAssemblerName(const util::StringView &newName) 368 { 369 assemblerName_ = newName; 370 } 371 ObjectFlags()372 ETSObjectFlags ObjectFlags() const 373 { 374 return flags_; 375 } 376 AddObjectFlag(ETSObjectFlags flag)377 void AddObjectFlag(ETSObjectFlags flag) 378 { 379 flags_ |= flag; 380 } 381 RemoveObjectFlag(ETSObjectFlags flag)382 void RemoveObjectFlag(ETSObjectFlags flag) 383 { 384 flags_ &= ~flag; 385 } 386 HasObjectFlag(ETSObjectFlags flag)387 bool HasObjectFlag(ETSObjectFlags flag) const 388 { 389 return (flags_ & flag) != 0; 390 } 391 GetFunctionalInterfaceInvokeType()392 ETSFunctionType *GetFunctionalInterfaceInvokeType() 393 { 394 ASSERT(HasObjectFlag(ETSObjectFlags::FUNCTIONAL)); 395 auto *invoke = GetOwnProperty<PropertyType::INSTANCE_METHOD>("invoke"); 396 ASSERT(invoke && invoke->TsType() && invoke->TsType()->IsETSFunctionType()); 397 return invoke->TsType()->AsETSFunctionType(); 398 } 399 BuiltInKind()400 ETSObjectFlags BuiltInKind() const 401 { 402 return static_cast<checker::ETSObjectFlags>(flags_ & ETSObjectFlags::BUILTIN_TYPE); 403 } 404 GetInstantiatedType(util::StringView hash)405 ETSObjectType *GetInstantiatedType(util::StringView hash) 406 { 407 auto found = instantiationMap_.find(hash); 408 if (found != instantiationMap_.end()) { 409 return found->second; 410 } 411 412 return nullptr; 413 } 414 GetTypeArgumentScope()415 varbinder::Scope *GetTypeArgumentScope() const 416 { 417 if (HasObjectFlag(ETSObjectFlags::ENUM) || !HasTypeFlag(TypeFlag::GENERIC)) { 418 return nullptr; 419 } 420 421 if (HasObjectFlag(ETSObjectFlags::CLASS)) { 422 ASSERT(declNode_->IsClassDefinition() && declNode_->AsClassDefinition()->TypeParams()); 423 return declNode_->AsClassDefinition()->TypeParams()->Scope(); 424 } 425 426 ASSERT(declNode_->IsTSInterfaceDeclaration() && declNode_->AsTSInterfaceDeclaration()->TypeParams()); 427 return declNode_->AsTSInterfaceDeclaration()->TypeParams()->Scope(); 428 } 429 GetInstantiationMap()430 InstantiationMap &GetInstantiationMap() 431 { 432 return instantiationMap_; 433 } 434 435 template <PropertyType TYPE> GetOwnProperty(const util::StringView & name)436 varbinder::LocalVariable *GetOwnProperty(const util::StringView &name) const 437 { 438 EnsurePropertiesInstantiated(); 439 auto found = properties_[static_cast<size_t>(TYPE)].find(name); 440 if (found != properties_[static_cast<size_t>(TYPE)].end()) { 441 return found->second; 442 } 443 return nullptr; 444 } 445 446 template <PropertyType TYPE> AddProperty(varbinder::LocalVariable * prop)447 void AddProperty(varbinder::LocalVariable *prop) 448 { 449 properties_[static_cast<size_t>(TYPE)].emplace(prop->Name(), prop); 450 propertiesInstantiated_ = true; 451 } 452 IsGeneric()453 [[nodiscard]] bool IsGeneric() const noexcept 454 { 455 return !typeArguments_.empty(); 456 } 457 458 std::vector<const varbinder::LocalVariable *> ForeignProperties() const; 459 varbinder::LocalVariable *GetProperty(const util::StringView &name, PropertySearchFlags flags) const; 460 std::vector<varbinder::LocalVariable *> GetAllProperties() const; 461 void CreatePropertyMap(ArenaAllocator *allocator); 462 varbinder::LocalVariable *CopyProperty(varbinder::LocalVariable *prop, ArenaAllocator *allocator, 463 TypeRelation *relation, GlobalTypesHolder *globalTypes); 464 std::vector<varbinder::LocalVariable *> Methods() const; 465 std::vector<varbinder::LocalVariable *> Fields() const; 466 varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(const util::StringView &name, 467 PropertySearchFlags flags) const; 468 varbinder::LocalVariable *CollectSignaturesForSyntheticType(ETSFunctionType *funcType, const util::StringView &name, 469 PropertySearchFlags flags) const; 470 bool CheckIdenticalFlags(ETSObjectFlags target) const; 471 bool CheckIdenticalVariable(varbinder::Variable *otherVar) const; 472 473 void Iterate(const PropertyTraverser &cb) const; 474 void ToString(std::stringstream &ss) const override; 475 void Identical(TypeRelation *relation, Type *other) override; 476 bool AssignmentSource(TypeRelation *relation, Type *target) override; 477 void AssignmentTarget(TypeRelation *relation, Type *source) override; 478 Type *Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes) override; 479 bool SubstituteTypeArgs(TypeRelation *relation, ArenaVector<Type *> &newTypeArgs, const Substitution *substitution); 480 void SetCopiedTypeProperties(TypeRelation *relation, ETSObjectType *copiedType, ArenaVector<Type *> &newTypeArgs, 481 const Substitution *substitution); 482 Type *Substitute(TypeRelation *relation, const Substitution *substitution) override; 483 void Cast(TypeRelation *relation, Type *target) override; 484 bool CastNumericObject(TypeRelation *relation, Type *target); 485 void IsSupertypeOf(TypeRelation *relation, Type *source) override; 486 Type *AsSuper(Checker *checker, varbinder::Variable *sourceVar) override; 487 ToAssemblerType(std::stringstream & ss)488 void ToAssemblerType([[maybe_unused]] std::stringstream &ss) const override 489 { 490 ss << assemblerName_; 491 } 492 493 static void DebugInfoTypeFromName(std::stringstream &ss, util::StringView asmName); 494 ToDebugInfoType(std::stringstream & ss)495 void ToDebugInfoType(std::stringstream &ss) const override 496 { 497 DebugInfoTypeFromName(ss, assemblerName_); 498 } 499 ToDebugInfoSignatureType(std::stringstream & ss)500 void ToDebugInfoSignatureType(std::stringstream &ss) const 501 { 502 ss << compiler::Signatures::GENERIC_BEGIN; 503 ss << assemblerName_; 504 ss << compiler::Signatures::GENERIC_END; 505 } 506 Allocator()507 ArenaAllocator *Allocator() const 508 { 509 return allocator_; 510 } 511 ResolveConditionExpr()512 std::tuple<bool, bool> ResolveConditionExpr() const override 513 { 514 return {false, false}; 515 } 516 517 protected: 518 virtual ETSFunctionType *CreateETSFunctionType(const util::StringView &name) const; 519 520 private: 521 template <size_t... IS> ETSObjectType(ArenaAllocator * allocator,util::StringView name,util::StringView assemblerName,ir::AstNode * declNode,ETSObjectFlags flags,std::index_sequence<IS...> s)522 explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assemblerName, 523 ir::AstNode *declNode, ETSObjectFlags flags, [[maybe_unused]] std::index_sequence<IS...> s) 524 : Type(TypeFlag::ETS_OBJECT), 525 allocator_(allocator), 526 name_(name), 527 assemblerName_(assemblerName), 528 declNode_(declNode), 529 interfaces_(allocator->Adapter()), 530 flags_(flags), 531 instantiationMap_(allocator->Adapter()), 532 typeArguments_(allocator->Adapter()), 533 constructSignatures_(allocator->Adapter()), 534 properties_ {(void(IS), PropertyMap {allocator->Adapter()})...} 535 { 536 } 537 538 /* Properties and construct signatures are instantiated lazily. */ 539 void InstantiateProperties() const; EnsurePropertiesInstantiated()540 void EnsurePropertiesInstantiated() const 541 { 542 if (!propertiesInstantiated_) { 543 InstantiateProperties(); 544 propertiesInstantiated_ = true; 545 } 546 } 547 std::unordered_map<util::StringView, const varbinder::LocalVariable *> CollectAllProperties() const; 548 void IdenticalUptoNullability(TypeRelation *relation, Type *other); 549 bool CastWideningNarrowing(TypeRelation *relation, Type *target, TypeFlag unboxFlags, TypeFlag wideningFlags, 550 TypeFlag narrowingFlags); 551 552 ArenaAllocator *allocator_; 553 util::StringView name_; 554 util::StringView assemblerName_; 555 ir::AstNode *declNode_; 556 ArenaVector<ETSObjectType *> interfaces_; 557 ETSObjectFlags flags_; 558 InstantiationMap instantiationMap_; 559 ArenaVector<Type *> typeArguments_; 560 ETSObjectType *superType_ {}; 561 ETSObjectType *enclosingType_ {}; 562 ETSObjectType *baseType_ {}; 563 564 // for lazy properties instantiation 565 TypeRelation *relation_ = nullptr; 566 const Substitution *substitution_ = nullptr; 567 mutable bool propertiesInstantiated_ = false; 568 mutable ArenaVector<Signature *> constructSignatures_; 569 mutable PropertyHolder properties_; 570 }; 571 } // namespace panda::es2panda::checker 572 573 #endif /* TYPESCRIPT_TYPES_FUNCTION_TYPE_H */ 574