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