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 "tupleType.h"
17
18 #include <typescript/checker.h>
19
20 namespace panda::es2panda::checker {
21
ConvertToArrayType(Checker * checker)22 Type *TupleType::ConvertToArrayType(Checker *checker)
23 {
24 ArenaVector<Type *> unionTypes(checker->Allocator()->Adapter());
25
26 for (const auto *it : desc_->properties) {
27 unionTypes.push_back(it->TsType());
28 }
29
30 Type *arrayType = checker->CreateUnionType(std::move(unionTypes));
31 return checker->Allocator()->New<ArrayType>(arrayType);
32 }
33
ToString(std::stringstream & ss) const34 void TupleType::ToString(std::stringstream &ss) const
35 {
36 if (readonly_) {
37 ss << "readonly ";
38 }
39 ss << "[";
40
41 if (namedMembers_.empty()) {
42 for (auto it = desc_->properties.begin(); it != desc_->properties.end(); it++) {
43 (*it)->TsType()->ToString(ss);
44 if ((*it)->HasFlag(binder::VariableFlags::OPTIONAL)) {
45 ss << "?";
46 }
47
48 if (std::next(it) != desc_->properties.end()) {
49 ss << ", ";
50 }
51 }
52 } else {
53 for (auto it = desc_->properties.begin(); it != desc_->properties.end(); it++) {
54 const util::StringView &memberName = FindNamedMemberName(*it);
55 ss << memberName;
56
57 if ((*it)->HasFlag(binder::VariableFlags::OPTIONAL)) {
58 ss << "?";
59 }
60
61 ss << ": ";
62 (*it)->TsType()->ToString(ss);
63 if (std::next(it) != desc_->properties.end()) {
64 ss << ", ";
65 }
66 }
67 }
68
69 ss << "]";
70 }
71
Identical(TypeRelation * relation,Type * other)72 void TupleType::Identical(TypeRelation *relation, Type *other)
73 {
74 if (other->IsObjectType() && other->AsObjectType()->IsTupleType()) {
75 TupleType *otherTuple = other->AsObjectType()->AsTupleType();
76 if (kind_ == otherTuple->Kind() && desc_->properties.size() == otherTuple->Properties().size()) {
77 for (size_t i = 0; i < desc_->properties.size(); i++) {
78 binder::LocalVariable *targetProp = desc_->properties[i];
79 binder::LocalVariable *sourceProp = otherTuple->Properties()[i];
80
81 if (targetProp->Flags() != sourceProp->Flags()) {
82 relation->Result(false);
83 return;
84 }
85
86 relation->IsIdenticalTo(targetProp->TsType(), sourceProp->TsType());
87
88 if (!relation->IsTrue()) {
89 return;
90 }
91 }
92 relation->Result(true);
93 }
94 }
95 }
96
AssignmentTarget(TypeRelation * relation,Type * source)97 void TupleType::AssignmentTarget(TypeRelation *relation, Type *source)
98 {
99 if (!source->IsObjectType() || !source->AsObjectType()->IsTupleType()) {
100 relation->Result(false);
101 return;
102 }
103
104 TupleType *sourceTuple = source->AsObjectType()->AsTupleType();
105 if (FixedLength() < sourceTuple->MinLength()) {
106 relation->Result(false);
107 return;
108 }
109
110 relation->Result(true);
111
112 const auto &sourceProperties = sourceTuple->Properties();
113 for (size_t i = 0; i < desc_->properties.size(); i++) {
114 auto *targetProp = desc_->properties[i];
115
116 if (i < sourceProperties.size()) {
117 if (!targetProp->HasFlag(binder::VariableFlags::OPTIONAL) &&
118 sourceProperties[i]->HasFlag(binder::VariableFlags::OPTIONAL)) {
119 relation->Result(false);
120 return;
121 }
122
123 Type *targetPropType = targetProp->TsType();
124 Type *sourcePropType = sourceProperties[i]->TsType();
125 if (!relation->IsAssignableTo(sourcePropType, targetPropType)) {
126 return;
127 }
128
129 continue;
130 }
131
132 if (!targetProp->HasFlag(binder::VariableFlags::OPTIONAL)) {
133 relation->Result(false);
134 return;
135 }
136 }
137
138 if (relation->IsTrue()) {
139 AssignIndexInfo(relation, sourceTuple);
140 }
141 }
142
GetTypeFacts() const143 TypeFacts TupleType::GetTypeFacts() const
144 {
145 if (desc_->properties.empty()) {
146 return TypeFacts::EMPTY_OBJECT_FACTS;
147 }
148
149 return TypeFacts::OBJECT_FACTS;
150 }
151
Instantiate(ArenaAllocator * allocator,TypeRelation * relation,GlobalTypesHolder * globalTypes)152 Type *TupleType::Instantiate(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes)
153 {
154 ObjectDescriptor *copiedDesc = allocator->New<ObjectDescriptor>(allocator);
155
156 desc_->Copy(allocator, copiedDesc, relation, globalTypes);
157
158 NamedTupleMemberPool copiedNamedMemberPool = namedMembers_;
159 ArenaVector<ElementFlags> copiedElementFlags(allocator->Adapter());
160
161 for (auto it : elementFlags_) {
162 copiedElementFlags.push_back(it);
163 }
164
165 return allocator->New<TupleType>(copiedDesc, std::move(copiedElementFlags), combinedFlags_, minLength_,
166 fixedLength_, readonly_, std::move(copiedNamedMemberPool));
167 }
168
169 } // namespace panda::es2panda::checker
170