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