• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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