1 /*
2 * Copyright (c) 2021-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 "etsParameterExpression.h"
17
18 #include "checker/ETSchecker.h"
19 #include "checker/TSchecker.h"
20 #include "compiler/core/ETSGen.h"
21 #include "compiler/core/pandagen.h"
22
23 namespace ark::es2panda::ir {
24
ETSParameterExpression(AnnotatedExpression * const identOrSpread,bool isOptional,ArenaAllocator * const allocator)25 ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, bool isOptional,
26 ArenaAllocator *const allocator)
27 : AnnotationAllowed<Expression>(AstNodeType::ETS_PARAMETER_EXPRESSION, allocator)
28 {
29 SetOptional(isOptional);
30
31 if (identOrSpread == nullptr) {
32 return;
33 }
34 identOrSpread->SetParent(this);
35 SetRange(identOrSpread->Range());
36 if (identOrSpread->IsIdentifier()) {
37 ident_ = identOrSpread->AsIdentifier();
38 } else if (identOrSpread->IsRestElement()) {
39 spread_ = identOrSpread->AsRestElement();
40 ES2PANDA_ASSERT(spread_->Argument()->IsIdentifier());
41 ident_ = spread_->Argument()->AsIdentifier();
42 ident_->SetParent(spread_);
43 } else {
44 ES2PANDA_UNREACHABLE();
45 }
46 }
47
ETSParameterExpression(AnnotatedExpression * const identOrSpread,ir::Expression * initializer,ArenaAllocator * const allocator)48 ETSParameterExpression::ETSParameterExpression(AnnotatedExpression *const identOrSpread, ir::Expression *initializer,
49 ArenaAllocator *const allocator)
50 : ETSParameterExpression(identOrSpread, true, allocator)
51 {
52 SetInitializer(initializer);
53 }
54
Name() const55 const util::StringView &ETSParameterExpression::Name() const noexcept
56 {
57 return ident_->Name();
58 }
59
Ident() const60 const Identifier *ETSParameterExpression::Ident() const noexcept
61 {
62 return ident_;
63 }
64
Ident()65 Identifier *ETSParameterExpression::Ident() noexcept
66 {
67 return ident_;
68 }
69
RestParameter() const70 const SpreadElement *ETSParameterExpression::RestParameter() const noexcept
71 {
72 return spread_;
73 }
74
RestParameter()75 SpreadElement *ETSParameterExpression::RestParameter() noexcept
76 {
77 return spread_;
78 }
79
Initializer() const80 const Expression *ETSParameterExpression::Initializer() const noexcept
81 {
82 return initializer_;
83 }
84
Initializer()85 Expression *ETSParameterExpression::Initializer() noexcept
86 {
87 return initializer_;
88 }
89
Variable() const90 varbinder::Variable *ETSParameterExpression::Variable() const noexcept
91 {
92 return ident_->Variable();
93 }
94
TypeAnnotation() const95 TypeNode const *ETSParameterExpression::TypeAnnotation() const noexcept
96 {
97 return !IsRestParameter() ? ident_->TypeAnnotation() : spread_->TypeAnnotation();
98 }
99
TypeAnnotation()100 TypeNode *ETSParameterExpression::TypeAnnotation() noexcept
101 {
102 return !IsRestParameter() ? ident_->TypeAnnotation() : spread_->TypeAnnotation();
103 }
104
SetTypeAnnotation(TypeNode * typeNode)105 void ETSParameterExpression::SetTypeAnnotation(TypeNode *typeNode) noexcept
106 {
107 !IsRestParameter() ? ident_->SetTsTypeAnnotation(typeNode) : spread_->SetTsTypeAnnotation(typeNode);
108 }
109
SetVariable(varbinder::Variable * const variable)110 void ETSParameterExpression::SetVariable(varbinder::Variable *const variable) noexcept
111 {
112 ident_->SetVariable(variable);
113 }
114
SetLexerSaved(util::StringView s)115 void ETSParameterExpression::SetLexerSaved(util::StringView s) noexcept
116 {
117 savedLexer_ = s;
118 }
119
LexerSaved() const120 util::StringView ETSParameterExpression::LexerSaved() const noexcept
121 {
122 return savedLexer_;
123 }
124
TransformChildren(const NodeTransformer & cb,std::string_view const transformationName)125 void ETSParameterExpression::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName)
126 {
127 if (IsRestParameter()) {
128 if (auto *transformedNode = cb(spread_); spread_ != transformedNode) {
129 spread_->SetTransformedNode(transformationName, transformedNode);
130 spread_ = transformedNode->AsRestElement();
131 }
132 ident_ = spread_->Argument()->AsIdentifier();
133 } else {
134 if (auto *transformedNode = cb(ident_); ident_ != transformedNode) {
135 ident_->SetTransformedNode(transformationName, transformedNode);
136 ident_ = transformedNode->AsIdentifier();
137 }
138 }
139
140 if (initializer_ != nullptr) {
141 if (auto *transformedNode = cb(initializer_); initializer_ != transformedNode) {
142 initializer_->SetTransformedNode(transformationName, transformedNode);
143 initializer_ = transformedNode->AsExpression();
144 }
145 }
146
147 for (auto *&it : Annotations()) {
148 if (auto *transformedNode = cb(it); it != transformedNode) {
149 it->SetTransformedNode(transformationName, transformedNode);
150 it = transformedNode->AsAnnotationUsage();
151 }
152 }
153 }
154
Iterate(const NodeTraverser & cb) const155 void ETSParameterExpression::Iterate(const NodeTraverser &cb) const
156 {
157 if (IsRestParameter()) {
158 cb(spread_);
159 } else {
160 cb(ident_);
161 }
162
163 if (initializer_ != nullptr) {
164 cb(initializer_);
165 }
166
167 for (auto *it : Annotations()) {
168 cb(it);
169 }
170 }
171
Dump(ir::AstDumper * const dumper) const172 void ETSParameterExpression::Dump(ir::AstDumper *const dumper) const
173 {
174 if (!IsRestParameter()) {
175 dumper->Add({{"type", "ETSParameterExpression"},
176 {"name", ident_},
177 {"initializer", AstDumper::Optional(initializer_)},
178 {"annotations", AstDumper::Optional(Annotations())}});
179 } else {
180 dumper->Add({{"type", "ETSParameterExpression"},
181 {"rest parameter", spread_},
182 {"annotations", AstDumper::Optional(Annotations())}});
183 }
184 }
185
Dump(ir::SrcDumper * const dumper) const186 void ETSParameterExpression::Dump(ir::SrcDumper *const dumper) const
187 {
188 for (auto *anno : Annotations()) {
189 anno->Dump(dumper);
190 }
191
192 if (IsRestParameter()) {
193 spread_->Dump(dumper);
194 } else {
195 if (ident_ != nullptr) {
196 ES2PANDA_ASSERT(ident_->IsAnnotatedExpression());
197 ident_->Dump(dumper);
198 if (isOptional_ && initializer_ == nullptr) {
199 dumper->Add("?");
200 }
201 auto typeAnnotation = ident_->AsAnnotatedExpression()->TypeAnnotation();
202 if (typeAnnotation != nullptr) {
203 dumper->Add(": ");
204 typeAnnotation->Dump(dumper);
205 }
206 }
207 if (initializer_ != nullptr) {
208 dumper->Add(" = ");
209 initializer_->Dump(dumper);
210 }
211 }
212 }
213
Compile(compiler::PandaGen * const pg) const214 void ETSParameterExpression::Compile(compiler::PandaGen *const pg) const
215 {
216 pg->GetAstCompiler()->Compile(this);
217 }
218
Compile(compiler::ETSGen * const etsg) const219 void ETSParameterExpression::Compile(compiler::ETSGen *const etsg) const
220 {
221 etsg->GetAstCompiler()->Compile(this);
222 }
223
Check(checker::TSChecker * const checker)224 checker::Type *ETSParameterExpression::Check(checker::TSChecker *const checker)
225 {
226 return checker->GetAnalyzer()->Check(this);
227 }
228
Check(checker::ETSChecker * const checker)229 checker::VerifiedType ETSParameterExpression::Check(checker::ETSChecker *const checker)
230 {
231 return {this, checker->GetAnalyzer()->Check(this)};
232 }
233
Clone(ArenaAllocator * const allocator,AstNode * const parent)234 ETSParameterExpression *ETSParameterExpression::Clone(ArenaAllocator *const allocator, AstNode *const parent)
235 {
236 AnnotatedExpression *identOrSpread = nullptr;
237 if (spread_ != nullptr) {
238 auto spreadClone = spread_->Clone(allocator, nullptr);
239 ES2PANDA_ASSERT(spreadClone != nullptr);
240 identOrSpread = spreadClone->AsAnnotatedExpression();
241 } else {
242 auto identClone = ident_->Clone(allocator, nullptr);
243 ES2PANDA_ASSERT(identClone != nullptr);
244 identOrSpread = identClone->AsAnnotatedExpression();
245 }
246 auto *const initializer =
247 initializer_ != nullptr ? initializer_->Clone(allocator, nullptr)->AsExpression() : nullptr;
248
249 auto *const clone = initializer_ != nullptr
250 ? allocator->New<ETSParameterExpression>(identOrSpread, initializer, allocator)
251 : allocator->New<ETSParameterExpression>(identOrSpread, isOptional_, allocator);
252 identOrSpread->SetParent(clone);
253
254 if (initializer != nullptr) {
255 initializer->SetParent(clone);
256 }
257
258 ES2PANDA_ASSERT(clone != nullptr);
259 if (parent != nullptr) {
260 clone->SetParent(parent);
261 }
262
263 clone->SetRequiredParams(extraValue_);
264
265 if (!Annotations().empty()) {
266 ArenaVector<AnnotationUsage *> annotationUsages {allocator->Adapter()};
267 for (auto *annotationUsage : Annotations()) {
268 auto *const annotationClone = annotationUsage->Clone(allocator, clone);
269 ES2PANDA_ASSERT(annotationClone != nullptr);
270 annotationUsages.push_back(annotationClone->AsAnnotationUsage());
271 }
272 clone->SetAnnotations(std::move(annotationUsages));
273 }
274
275 return clone;
276 }
277
Construct(ArenaAllocator * allocator)278 ETSParameterExpression *ETSParameterExpression::Construct(ArenaAllocator *allocator)
279 {
280 return allocator->New<ETSParameterExpression>(nullptr, false, allocator);
281 }
282
CopyTo(AstNode * other) const283 void ETSParameterExpression::CopyTo(AstNode *other) const
284 {
285 auto otherImpl = other->AsETSParameterExpression();
286
287 otherImpl->ident_ = ident_;
288 otherImpl->initializer_ = initializer_;
289 otherImpl->spread_ = spread_;
290 otherImpl->savedLexer_ = savedLexer_;
291 otherImpl->extraValue_ = extraValue_;
292 otherImpl->isOptional_ = isOptional_;
293
294 AnnotationAllowed<Expression>::CopyTo(other);
295 }
296
297 } // namespace ark::es2panda::ir
298