• 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 #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 << "std.core.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 << "std.core.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 
ApplySubstitution(TypeRelation * relation)260 void ETSTypeAliasType::ApplySubstitution(TypeRelation *relation)
261 {
262     ASSERT(base_ == nullptr);
263 
264     const util::StringView hash = relation->GetChecker()->AsETSChecker()->GetHashFromTypeArguments(typeArguments_);
265     EmplaceInstantiatedType(hash, this);
266 
267     auto getTypes = [this]() {
268         std::vector<ETSTypeAliasType *> types;
269 
270         for (auto [name, type] : instantiationMap_) {
271             if (type->targetType_ == nullptr) {
272                 types.push_back(type);
273             }
274         }
275 
276         return types;
277     };
278 
279     std::vector<ETSTypeAliasType *> types;
280 
281     while (!(types = getTypes(), types.empty())) {
282         for (auto type : types) {
283             type->SetTargetType(type->parent_->targetType_->Substitute(relation, type->substitution_));
284         }
285     }
286 }
287 
SetTypeArguments(ArenaVector<Type * > typeArguments)288 void ETSTypeAliasType::SetTypeArguments(ArenaVector<Type *> typeArguments)
289 {
290     typeArguments_ = std::move(typeArguments);
291 }
292 
Substitute(TypeRelation * relation,const Substitution * substitution)293 Type *ETSTypeAliasType::Substitute(TypeRelation *relation, const Substitution *substitution)
294 {
295     if (substitution == nullptr || substitution->empty()) {
296         return this;
297     }
298 
299     auto *const checker = relation->GetChecker()->AsETSChecker();
300 
301     ArenaVector<Type *> newTypeArgs {checker->Allocator()->Adapter()};
302 
303     if (!SubstituteTypeArgs(relation, newTypeArgs, substitution)) {
304         return this;
305     }
306 
307     const util::StringView hash = checker->GetHashFromTypeArguments(newTypeArgs);
308 
309     ETSTypeAliasType *copiedType = GetInstantiatedType(hash);
310     if (copiedType != nullptr) {
311         return copiedType;
312     }
313 
314     copiedType = checker->CreateETSTypeAliasType(name_, declNode_, isRecursive_);
315     copiedType->base_ = base_ == nullptr ? this : base_;
316     copiedType->parent_ = this;
317     copiedType->substitution_ = substitution;
318     copiedType->typeArguments_ = newTypeArgs;
319 
320     EmplaceInstantiatedType(hash, copiedType);
321 
322     if (targetType_ != nullptr) {
323         copiedType->SetTargetType(targetType_->Substitute(relation, substitution));
324     }
325 
326     return copiedType;
327 }
328 
329 }  // namespace ark::es2panda::checker
330