1 /**
2 * Copyright (c) 2023-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 "etsTuple.h"
17
18 #include "checker/ETSchecker.h"
19 #include "checker/types/ets/etsTupleType.h"
20
21 namespace ark::es2panda::ir {
22
TransformChildren(const NodeTransformer & cb,std::string_view const transformationName)23 void ETSTuple::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
24 {
25 for (auto *&it : GetTupleTypeAnnotationsList()) {
26 if (auto *transformedNode = cb(it); it != transformedNode) {
27 it->SetTransformedNode(transformationName, transformedNode);
28 it = static_cast<TypeNode *>(transformedNode);
29 }
30 }
31
32 for (auto *&it : VectorIterationGuard(Annotations())) {
33 if (auto *transformedNode = cb(it); it != transformedNode) {
34 it->SetTransformedNode(transformationName, transformedNode);
35 it = transformedNode->AsAnnotationUsage();
36 }
37 }
38 }
39
Iterate(const NodeTraverser & cb) const40 void ETSTuple::Iterate(const NodeTraverser &cb) const
41 {
42 for (auto *const it : GetTupleTypeAnnotationsList()) {
43 cb(it);
44 }
45
46 for (auto *it : VectorIterationGuard(Annotations())) {
47 cb(it);
48 }
49 }
50
Dump(ir::AstDumper * const dumper) const51 void ETSTuple::Dump(ir::AstDumper *const dumper) const
52 {
53 dumper->Add({{"type", "ETSTuple"},
54 {"types", AstDumper::Optional(typeAnnotationList_)},
55 {"annotations", AstDumper::Optional(Annotations())}});
56 }
57
Dump(ir::SrcDumper * const dumper) const58 void ETSTuple::Dump(ir::SrcDumper *const dumper) const
59 {
60 for (auto *anno : Annotations()) {
61 anno->Dump(dumper);
62 }
63 dumper->Add("[");
64 for (const auto *const typeAnnot : typeAnnotationList_) {
65 typeAnnot->Dump(dumper);
66 if (typeAnnot != typeAnnotationList_.back()) {
67 dumper->Add(", ");
68 }
69 }
70 dumper->Add("]");
71 }
72
Compile(compiler::PandaGen * const pg) const73 void ETSTuple::Compile([[maybe_unused]] compiler::PandaGen *const pg) const {}
Compile(compiler::ETSGen * const etsg) const74 void ETSTuple::Compile([[maybe_unused]] compiler::ETSGen *const etsg) const {}
75
Check(checker::TSChecker * const checker)76 checker::Type *ETSTuple::Check([[maybe_unused]] checker::TSChecker *const checker)
77 {
78 return nullptr;
79 }
80
Check(checker::ETSChecker * const checker)81 checker::VerifiedType ETSTuple::Check([[maybe_unused]] checker::ETSChecker *const checker)
82 {
83 return {this, GetType(checker)};
84 }
85
GetHolderTypeForTuple(checker::ETSChecker * const checker,ArenaVector<checker::Type * > & typeList)86 checker::Type *ETSTuple::GetHolderTypeForTuple(checker::ETSChecker *const checker,
87 ArenaVector<checker::Type *> &typeList)
88 {
89 if (typeList.empty()) {
90 return checker->GlobalETSObjectType();
91 }
92
93 const bool allElementsAreSame = std::all_of(typeList.begin(), typeList.end(), [&checker, &typeList](auto *element) {
94 return checker->Relation()->IsIdenticalTo(typeList[0], element);
95 });
96 if (allElementsAreSame) {
97 return typeList[0];
98 }
99
100 std::for_each(typeList.begin(), typeList.end(), [checker](auto &t) { t = checker->MaybeBoxType(t); });
101
102 auto ctypes = typeList;
103 return checker->CreateETSUnionType(std::move(ctypes));
104 }
105
GetType(checker::ETSChecker * const checker)106 checker::Type *ETSTuple::GetType(checker::ETSChecker *const checker)
107 {
108 if (TsType() != nullptr) {
109 return TsType();
110 }
111 checker->CheckAnnotations(Annotations());
112
113 // NOTE (smartin): Remove, when TupleN is handled in codegen
114 constexpr uint8_t MAX_TUPLE_ARITY = 16;
115 if (GetTupleTypeAnnotationsList().size() > MAX_TUPLE_ARITY) {
116 checker->LogError(diagnostic::TUPLEN_NOT_IMPLEMENTED, {}, Start());
117 return checker->InvalidateType(this);
118 }
119
120 ArenaVector<checker::Type *> typeList(checker->ProgramAllocator()->Adapter());
121
122 bool isTypeError = false;
123 for (auto *const typeAnnotation : GetTupleTypeAnnotationsList()) {
124 auto *const checkedType = typeAnnotation->GetType(checker);
125 if (!isTypeError && checkedType->IsTypeError()) {
126 isTypeError = true;
127 }
128 typeList.emplace_back(checkedType);
129 }
130
131 if (isTypeError) {
132 SetTsType(checker->GlobalTypeError());
133 return checker->GlobalTypeError();
134 }
135
136 auto *tupleType = checker->ProgramAllocator()->New<checker::ETSTupleType>(checker, typeList);
137
138 if (IsReadonlyType()) {
139 ES2PANDA_ASSERT(checker->GetReadonlyType(tupleType));
140 tupleType = checker->GetReadonlyType(tupleType)->AsETSTupleType();
141 }
142
143 SetTsType(tupleType);
144 return TsType();
145 }
146
Clone(ArenaAllocator * const allocator,AstNode * const parent)147 ETSTuple *ETSTuple::Clone(ArenaAllocator *const allocator, AstNode *const parent)
148 {
149 auto *const clone = allocator->New<ETSTuple>(allocator, size_);
150 ES2PANDA_ASSERT(clone != nullptr);
151
152 clone->AddModifier(flags_);
153
154 if (parent != nullptr) {
155 clone->SetParent(parent);
156 }
157
158 ArenaVector<TypeNode *> typeList(allocator->Adapter());
159 for (auto *const type : typeAnnotationList_) {
160 auto *const t = type->Clone(allocator, clone);
161 typeList.push_back(t);
162 }
163
164 if (!Annotations().empty()) {
165 ArenaVector<AnnotationUsage *> annotationUsages {allocator->Adapter()};
166 for (auto *annotationUsage : Annotations()) {
167 auto *const annotationClone = annotationUsage->Clone(allocator, clone);
168 ES2PANDA_ASSERT(annotationClone != nullptr);
169 annotationUsages.push_back(annotationClone->AsAnnotationUsage());
170 }
171 clone->SetAnnotations(std::move(annotationUsages));
172 }
173 clone->SetTypeAnnotationsList(std::move(typeList));
174
175 clone->SetRange(Range());
176 return clone;
177 }
178
179 } // namespace ark::es2panda::ir
180