• 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 #include "etsTypeAliasType.h"
17 
18 #include "varbinder/variable.h"
19 #include "checker/ETSchecker.h"
20 #include "checker/ets/conversion.h"
21 #include "checker/types/typeRelation.h"
22 #include "checker/types/globalTypesHolder.h"
23 
24 namespace ark::es2panda::checker {
25 
ETSTypeAliasType(ETSChecker * checker,util::StringView name,const ir::AstNode * declNode,bool isRecursive)26 ETSTypeAliasType::ETSTypeAliasType(ETSChecker *checker, util::StringView name, const ir::AstNode *declNode,
27                                    bool isRecursive)
28     : Type(TypeFlag::ETS_TYPE_ALIAS),
29       name_(name),
30       declNode_(declNode),
31       isRecursive_(isRecursive),
32       instantiationMap_(checker->Allocator()->Adapter()),
33       typeArguments_(checker->Allocator()->Adapter())
34 {
35 }
36 
ToString(std::stringstream & ss,bool precise) const37 void ETSTypeAliasType::ToString(std::stringstream &ss, bool precise) const
38 {
39     if (!isRecursive_) {
40         targetType_->ToString(ss, precise);
41         return;
42     }
43 
44     if (precise) {
45         ToAssemblerType(ss);
46     } else {
47         ss << name_;
48     }
49 
50     if (!typeArguments_.empty()) {
51         ss << compiler::Signatures::GENERIC_BEGIN;
52         for (auto arg = typeArguments_.cbegin(); arg != typeArguments_.cend(); ++arg) {
53             (*arg)->ToString(ss, precise);
54 
55             if (next(arg) != typeArguments_.cend()) {
56                 ss << lexer::TokenToString(lexer::TokenType::PUNCTUATOR_COMMA);
57             }
58         }
59         ss << compiler::Signatures::GENERIC_END;
60     }
61 }
62 
ToAssemblerType(std::stringstream & ss) const63 void ETSTypeAliasType::ToAssemblerType(std::stringstream &ss) const
64 {
65     if (targetType_ == nullptr || recursionCount_) {
66         ss << compiler::Signatures::BUILTIN_OBJECT;
67         return;
68     }
69 
70     recursionCount_ = true;
71     targetType_->ToAssemblerType(ss);
72     recursionCount_ = false;
73 }
74 
ToAssemblerTypeWithRank(std::stringstream & ss) const75 void ETSTypeAliasType::ToAssemblerTypeWithRank(std::stringstream &ss) const
76 {
77     if (targetType_ == nullptr || recursionCount_) {
78         ss << compiler::Signatures::BUILTIN_OBJECT;
79         return;
80     }
81 
82     recursionCount_ = true;
83     targetType_->ToAssemblerTypeWithRank(ss);
84     recursionCount_ = false;
85 }
86 
ToDebugInfoType(std::stringstream & ss) const87 void ETSTypeAliasType::ToDebugInfoType(std::stringstream &ss) const
88 {
89     if (isRecursive_) {
90         ss << name_;
91         return;
92     }
93 
94     targetType_->ToDebugInfoType(ss);
95 }
96 
IsArgumentsIdentical(TypeRelation * relation,Type * other)97 bool ETSTypeAliasType::IsArgumentsIdentical(TypeRelation *relation, Type *other)
98 {
99     auto const otherTypeArguments = other->AsETSTypeAliasType()->typeArguments_;
100 
101     auto const argsNumber = typeArguments_.size();
102     if (argsNumber != otherTypeArguments.size()) {
103         return false;
104     }
105 
106     for (size_t idx = 0U; idx < argsNumber; ++idx) {
107         if (typeArguments_[idx]->IsWildcardType() || otherTypeArguments[idx]->IsWildcardType()) {
108             continue;
109         }
110         if (!relation->IsIdenticalTo(typeArguments_[idx], otherTypeArguments[idx])) {
111             return false;
112         }
113     }
114 
115     return true;
116 }
117 
Identical(TypeRelation * relation,Type * other)118 void ETSTypeAliasType::Identical(TypeRelation *relation, Type *other)
119 {
120     if (other->IsETSTypeAliasType() && other->AsETSTypeAliasType()->IsRecursive() && isRecursive_) {
121         if (other->AsETSTypeAliasType()->GetDeclNode() == this->declNode_) {
122             relation->Result(IsArgumentsIdentical(relation, other));
123             return;
124         }
125     }
126 
127     if (targetType_ != nullptr) {
128         relation->IsIdenticalTo(other, targetType_);
129     }
130 }
131 
AssignmentTarget(TypeRelation * relation,Type * source)132 void ETSTypeAliasType::AssignmentTarget(TypeRelation *relation, Type *source)
133 {
134     if (source->IsETSTypeAliasType()) {
135         relation->IsIdenticalTo(this, source);
136     }
137 
138     if (!relation->IsTrue() && relation->IsAtTypeDepthLimit(GetBaseType()) && targetType_ != nullptr) {
139         relation->IncreaseTypeRecursionCount(GetBaseType());
140         relation->IsAssignableTo(source, targetType_);
141         relation->DecreaseTypeRecursionCount(GetBaseType());
142     }
143 }
144 
AssignmentSource(TypeRelation * relation,Type * target)145 bool ETSTypeAliasType::AssignmentSource(TypeRelation *relation, Type *target)
146 {
147     if (target->IsETSTypeAliasType()) {
148         relation->IsIdenticalTo(target, this);
149     }
150 
151     if (!relation->IsTrue() && relation->IsAtTypeDepthLimit(GetBaseType()) && targetType_ != nullptr) {
152         relation->IncreaseTypeRecursionCount(GetBaseType());
153         relation->IsAssignableTo(targetType_, target);
154         relation->DecreaseTypeRecursionCount(GetBaseType());
155     }
156 
157     return relation->IsTrue();
158 }
159 
Cast(TypeRelation * const relation,Type * const target)160 void ETSTypeAliasType::Cast(TypeRelation *const relation, Type *const target)
161 {
162     if (target->IsETSTypeAliasType()) {
163         relation->IsIdenticalTo(this, target);
164     }
165 
166     if (!relation->IsTrue() && relation->IsAtTypeDepthLimit(GetBaseType())) {
167         relation->IncreaseTypeRecursionCount(GetBaseType());
168         targetType_->Cast(relation, target);
169         relation->DecreaseTypeRecursionCount(GetBaseType());
170     }
171 }
172 
CastTarget(TypeRelation * relation,Type * source)173 void ETSTypeAliasType::CastTarget(TypeRelation *relation, Type *source)
174 {
175     if (source->IsETSTypeAliasType()) {
176         relation->IsIdenticalTo(this, source);
177     }
178 
179     if (!relation->IsTrue() && relation->IsAtTypeDepthLimit(GetBaseType())) {
180         relation->IncreaseTypeRecursionCount(GetBaseType());
181         targetType_->CastTarget(relation, source);
182         relation->DecreaseTypeRecursionCount(GetBaseType());
183     }
184 }
185 
IsSupertypeOf(TypeRelation * relation,Type * source)186 void ETSTypeAliasType::IsSupertypeOf(TypeRelation *relation, Type *source)
187 {
188     if (source->IsETSTypeAliasType()) {
189         relation->IsIdenticalTo(this, source);
190     }
191 
192     if (!relation->IsTrue() && relation->IsAtTypeDepthLimit(GetBaseType()) && targetType_ != nullptr) {
193         relation->IncreaseTypeRecursionCount(GetBaseType());
194         relation->IsSupertypeOf(targetType_, source);
195         relation->DecreaseTypeRecursionCount(GetBaseType());
196     }
197 }
198 
IsSubtypeOf(TypeRelation * relation,Type * target)199 void ETSTypeAliasType::IsSubtypeOf(TypeRelation *relation, Type *target)
200 {
201     if (target->IsETSTypeAliasType()) {
202         relation->IsIdenticalTo(this, target);
203     }
204 
205     if (!relation->IsTrue() && relation->IsAtTypeDepthLimit(GetBaseType()) && targetType_ != nullptr) {
206         relation->IncreaseTypeRecursionCount(GetBaseType());
207         relation->IsSupertypeOf(target, targetType_);
208         relation->DecreaseTypeRecursionCount(GetBaseType());
209     }
210 }
211 
Rank() const212 uint32_t ETSTypeAliasType::Rank() const
213 {
214     if (isRecursive_) {
215         return 0;
216     }
217 
218     return targetType_->Rank();
219 }
220 
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)221 Type *ETSTypeAliasType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
222 {
223     return targetType_->Instantiate(allocator, relation, globalTypes);
224 }
225 
GetInstantiatedType(util::StringView hash)226 ETSTypeAliasType *ETSTypeAliasType::GetInstantiatedType(util::StringView hash)
227 {
228     auto &instantiationMap = base_ == nullptr ? instantiationMap_ : base_->instantiationMap_;
229 
230     auto found = instantiationMap.find(hash);
231     if (found != instantiationMap.end()) {
232         return found->second;
233     }
234 
235     return nullptr;
236 }
237 
EmplaceInstantiatedType(util::StringView hash,ETSTypeAliasType * emplaceType)238 void ETSTypeAliasType::EmplaceInstantiatedType(util::StringView hash, ETSTypeAliasType *emplaceType)
239 {
240     auto &instantiationMap = base_ == nullptr ? instantiationMap_ : base_->instantiationMap_;
241 
242     instantiationMap.try_emplace(hash, emplaceType);
243 }
244 
SubstituteTypeArgs(TypeRelation * const relation,ArenaVector<Type * > & newTypeArgs,const Substitution * const substitution)245 bool ETSTypeAliasType::SubstituteTypeArgs(TypeRelation *const relation, ArenaVector<Type *> &newTypeArgs,
246                                           const Substitution *const substitution)
247 {
248     bool anyChange = false;
249     newTypeArgs.reserve(typeArguments_.size());
250 
251     for (auto *const arg : typeArguments_) {
252         auto *const newArg = arg->Substitute(relation, substitution);
253         newTypeArgs.push_back(newArg);
254         anyChange = anyChange || (newArg != arg);
255     }
256 
257     return anyChange;
258 }
259 
SetTypeArguments(ArenaVector<Type * > typeArguments)260 void ETSTypeAliasType::SetTypeArguments(ArenaVector<Type *> typeArguments)
261 {
262     typeArguments_ = std::move(typeArguments);
263 }
264 
Substitute(TypeRelation * relation,const Substitution * substitution)265 Type *ETSTypeAliasType::Substitute(TypeRelation *relation, const Substitution *substitution)
266 {
267     if (substitution == nullptr || substitution->empty()) {
268         return this;
269     }
270 
271     auto *const checker = relation->GetChecker()->AsETSChecker();
272 
273     ArenaVector<Type *> newTypeArgs {checker->Allocator()->Adapter()};
274 
275     if (!SubstituteTypeArgs(relation, newTypeArgs, substitution)) {
276         return this;
277     }
278 
279     const util::StringView hash = checker->GetHashFromTypeArguments(newTypeArgs);
280 
281     ETSTypeAliasType *copiedType = GetInstantiatedType(hash);
282     if (copiedType != nullptr) {
283         return copiedType;
284     }
285 
286     copiedType = checker->CreateETSTypeAliasType(name_, declNode_, isRecursive_);
287     copiedType->base_ = base_ == nullptr ? this : base_;
288     copiedType->parent_ = this;
289     copiedType->substitution_ = substitution;
290     copiedType->typeArguments_ = newTypeArgs;
291 
292     EmplaceInstantiatedType(hash, copiedType);
293 
294     if (targetType_ != nullptr) {
295         copiedType->SetTargetType(targetType_->Substitute(relation, substitution));
296     }
297 
298     return copiedType;
299 }
300 
301 }  // namespace ark::es2panda::checker
302