• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 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 "unionType.h"
17 
18 #include <typescript/types/globalTypesHolder.h>
19 
20 namespace panda::es2panda::checker {
21 
ToString(std::stringstream & ss) const22 void UnionType::ToString(std::stringstream &ss) const
23 {
24     for (auto it = constituentTypes_.begin(); it != constituentTypes_.end(); it++) {
25         (*it)->ToString(ss);
26         if (std::next(it) != constituentTypes_.end()) {
27             ss << " | ";
28         }
29     }
30 }
31 
EachTypeRelatedToSomeType(TypeRelation * relation,UnionType * source,UnionType * target)32 bool UnionType::EachTypeRelatedToSomeType(TypeRelation *relation, UnionType *source, UnionType *target)
33 {
34     return std::all_of(source->constituentTypes_.begin(), source->constituentTypes_.end(),
35                        [relation, target](auto *s) { return TypeRelatedToSomeType(relation, s, target); });
36 }
37 
TypeRelatedToSomeType(TypeRelation * relation,Type * source,UnionType * target)38 bool UnionType::TypeRelatedToSomeType(TypeRelation *relation, Type *source, UnionType *target)
39 {
40     return std::any_of(target->constituentTypes_.begin(), target->constituentTypes_.end(),
41                        [relation, source](auto *t) { return relation->IsIdenticalTo(source, t); });
42 }
43 
Identical(TypeRelation * relation,Type * other)44 void UnionType::Identical(TypeRelation *relation, Type *other)
45 {
46     if (other->IsUnionType()) {
47         if (EachTypeRelatedToSomeType(relation, this, other->AsUnionType()) &&
48             EachTypeRelatedToSomeType(relation, other->AsUnionType(), this)) {
49             relation->Result(true);
50             return;
51         }
52     }
53 
54     relation->Result(false);
55 }
56 
AssignmentSource(TypeRelation * relation,Type * target)57 bool UnionType::AssignmentSource(TypeRelation *relation, Type *target)
58 {
59     for (auto *it : constituentTypes_) {
60         if (!relation->IsAssignableTo(it, target)) {
61             return false;
62         }
63     }
64 
65     relation->Result(true);
66     return true;
67 }
68 
AssignmentTarget(TypeRelation * relation,Type * source)69 void UnionType::AssignmentTarget(TypeRelation *relation, Type *source)
70 {
71     for (auto *it : constituentTypes_) {
72         if (relation->IsAssignableTo(source, it)) {
73             return;
74         }
75     }
76 }
77 
GetTypeFacts() const78 TypeFacts UnionType::GetTypeFacts() const
79 {
80     TypeFacts facts = TypeFacts::NONE;
81 
82     for (auto *it : constituentTypes_) {
83         facts |= it->GetTypeFacts();
84     }
85 
86     return facts;
87 }
88 
RemoveDuplicatedTypes(TypeRelation * relation,ArenaVector<Type * > & constituentTypes)89 void UnionType::RemoveDuplicatedTypes(TypeRelation *relation, ArenaVector<Type *> &constituentTypes)
90 {
91     auto compare = constituentTypes.begin();
92 
93     while (compare != constituentTypes.end()) {
94         auto it = compare + 1;
95 
96         while (it != constituentTypes.end()) {
97             relation->Result(false);
98 
99             (*compare)->Identical(relation, *it);
100 
101             if (relation->IsTrue()) {
102                 it = constituentTypes.erase(it);
103             } else {
104                 it++;
105             }
106         }
107 
108         compare++;
109     }
110 }
111 
HandleUnionType(UnionType * unionType,GlobalTypesHolder * globalTypesHolder)112 Type *UnionType::HandleUnionType(UnionType *unionType, GlobalTypesHolder *globalTypesHolder)
113 {
114     if (unionType->HasConstituentFlag(TypeFlag::ANY)) {
115         return globalTypesHolder->GlobalAnyType();
116     }
117 
118     if (unionType->HasConstituentFlag(TypeFlag::UNKNOWN)) {
119         return globalTypesHolder->GlobalUnknownType();
120     }
121 
122     RemoveRedundantLiteralTypesFromUnion(unionType);
123 
124     if (unionType->ConstituentTypes().size() == 1) {
125         return unionType->ConstituentTypes()[0];
126     }
127 
128     return unionType;
129 }
130 
RemoveRedundantLiteralTypesFromUnion(UnionType * type)131 void UnionType::RemoveRedundantLiteralTypesFromUnion(UnionType *type)
132 {
133     bool removeNumberLiterals = false;
134     bool removeStringLiterals = false;
135     bool removeBigintLiterals = false;
136     bool removeBooleanLiterals = false;
137 
138     if (type->HasConstituentFlag(TypeFlag::NUMBER) && type->HasConstituentFlag(TypeFlag::NUMBER_LITERAL)) {
139         removeNumberLiterals = true;
140     }
141 
142     if (type->HasConstituentFlag(TypeFlag::STRING) && type->HasConstituentFlag(TypeFlag::STRING_LITERAL)) {
143         removeStringLiterals = true;
144     }
145 
146     if (type->HasConstituentFlag(TypeFlag::BIGINT) && type->HasConstituentFlag(TypeFlag::BIGINT_LITERAL)) {
147         removeBigintLiterals = true;
148     }
149 
150     if (type->HasConstituentFlag(TypeFlag::BOOLEAN) && type->HasConstituentFlag(TypeFlag::BOOLEAN_LITERAL)) {
151         removeBooleanLiterals = true;
152     }
153 
154     auto &constituentTypes = type->ConstituentTypes();
155     /* TODO(dbatyai): use std::erase_if */
156     auto it = constituentTypes.begin();
157     while (it != constituentTypes.end()) {
158         if ((removeNumberLiterals && (*it)->IsNumberLiteralType()) ||
159             (removeStringLiterals && (*it)->IsStringLiteralType()) ||
160             (removeBigintLiterals && (*it)->IsBigintLiteralType()) ||
161             (removeBooleanLiterals && (*it)->IsBooleanLiteralType())) {
162             type->RemoveConstituentFlag((*it)->TypeFlags());
163             it = constituentTypes.erase(it);
164             continue;
165         }
166 
167         it++;
168     }
169 }
170 
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)171 Type *UnionType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
172 {
173     ArenaVector<Type *> copiedConstituents(constituentTypes_.size(), allocator->Adapter());
174 
175     for (auto *it : constituentTypes_) {
176         copiedConstituents.push_back(it->Instantiate(allocator, relation, globalTypes));
177     }
178 
179     RemoveDuplicatedTypes(relation, copiedConstituents);
180 
181     if (copiedConstituents.size() == 1) {
182         return copiedConstituents[0];
183     }
184 
185     Type *newUnionType = allocator->New<UnionType>(std::move(copiedConstituents));
186     CHECK_NOT_NULL(newUnionType);
187 
188     return HandleUnionType(newUnionType->AsUnionType(), globalTypes);
189 }
190 
191 }  // namespace panda::es2panda::checker
192