• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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