• 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 "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