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