• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "astNode.h"
17 #include "ir/astDump.h"
18 #include "ir/srcDump.h"
19 #include "ir/typed.h"
20 
21 namespace ark::es2panda::ir {
22 
AstNode(AstNode const & other)23 AstNode::AstNode(AstNode const &other)
24 {
25     range_ = other.range_;
26     type_ = other.type_;
27     if (other.variable_ != nullptr) {
28         variable_ = other.variable_;
29     }
30     flags_ = other.flags_;
31     astNodeFlags_ = other.astNodeFlags_;
32     // boxing_unboxing_flags_ {};  leave default value!
33 }
34 
IsExported() const35 [[nodiscard]] bool AstNode::IsExported() const noexcept
36 {
37     if (UNLIKELY(IsClassDefinition())) {
38         return parent_->IsExported();
39     }
40 
41     return (flags_ & ModifierFlags::EXPORT) != 0;
42 }
43 
IsDefaultExported() const44 [[nodiscard]] bool AstNode::IsDefaultExported() const noexcept
45 {
46     if (UNLIKELY(IsClassDefinition())) {
47         return parent_->IsDefaultExported();
48     }
49 
50     return (flags_ & ModifierFlags::DEFAULT_EXPORT) != 0;
51 }
52 
IsExportedType() const53 [[nodiscard]] bool AstNode::IsExportedType() const noexcept
54 {
55     if (UNLIKELY(IsClassDefinition())) {
56         return this->parent_->IsExportedType();
57     }
58 
59     return (flags_ & ModifierFlags::EXPORT_TYPE) != 0;
60 }
61 
HasExportAlias() const62 [[nodiscard]] bool AstNode::HasExportAlias() const noexcept
63 {
64     if (UNLIKELY(IsClassDefinition())) {
65         return parent_->HasExportAlias();
66     }
67 
68     return (astNodeFlags_ & AstNodeFlags::HAS_EXPORT_ALIAS) != 0;
69 }
70 
IsScopeBearer() const71 bool AstNode::IsScopeBearer() const noexcept
72 {
73     return false;
74 }
75 
Scope() const76 varbinder::Scope *AstNode::Scope() const noexcept
77 {
78     ES2PANDA_UNREACHABLE();
79 }
80 
ClearScope()81 void AstNode::ClearScope() noexcept
82 {
83     ES2PANDA_UNREACHABLE();
84 }
85 
AsClassElement()86 ir::ClassElement *AstNode::AsClassElement()
87 {
88     ES2PANDA_ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock());
89     return reinterpret_cast<ir::ClassElement *>(this);
90 }
91 
AsClassElement() const92 const ir::ClassElement *AstNode::AsClassElement() const
93 {
94     ES2PANDA_ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock());
95     return reinterpret_cast<const ir::ClassElement *>(this);
96 }
97 
98 template <typename R, typename T>
GetTopStatementImpl(T * self)99 static R GetTopStatementImpl(T *self)
100 {
101     auto iter = self;
102 
103     while (iter->Parent()) {
104         iter = iter->Parent();
105     }
106 
107     return reinterpret_cast<R>(iter);
108 }
109 
GetTopStatement()110 ir::BlockStatement *AstNode::GetTopStatement()
111 {
112     return GetTopStatementImpl<ir::BlockStatement *>(this);
113 }
114 
GetTopStatement() const115 const ir::BlockStatement *AstNode::GetTopStatement() const
116 {
117     return GetTopStatementImpl<const ir::BlockStatement *>(this);
118 }
119 
Clone(ArenaAllocator * const allocator,AstNode * const parent)120 AstNode *AstNode::Clone([[maybe_unused]] ArenaAllocator *const allocator, [[maybe_unused]] AstNode *const parent)
121 {
122     ES2PANDA_UNREACHABLE();
123 }
124 
TransformChildrenRecursively(const NodeTransformer & cb,std::string_view transformationName)125 void AstNode::TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName)
126 {  // post-order, but use when you don't care about the order
127     TransformChildrenRecursivelyPostorder(cb, transformationName);
128 }
129 
TransformChildrenRecursivelyPreorder(const NodeTransformer & cb,std::string_view transformationName)130 void AstNode::TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName)
131 {
132     TransformChildren(
133         [=](AstNode *child) {
134             auto *res = cb(child);
135             res->TransformChildrenRecursivelyPreorder(cb, transformationName);
136             return res;
137         },
138         transformationName);
139 }
140 
TransformChildrenRecursivelyPostorder(const NodeTransformer & cb,std::string_view transformationName)141 void AstNode::TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName)
142 {
143     TransformChildren(
144         [=](AstNode *child) {
145             child->TransformChildrenRecursivelyPostorder(cb, transformationName);
146             return cb(child);
147         },
148         transformationName);
149 }
150 
IterateRecursively(const NodeTraverser & cb) const151 void AstNode::IterateRecursively(const NodeTraverser &cb) const
152 {  // pre-order, use when you don't care
153     IterateRecursivelyPreorder(cb);
154 }
155 
IterateRecursivelyPreorder(const NodeTraverser & cb) const156 void AstNode::IterateRecursivelyPreorder(const NodeTraverser &cb) const
157 {
158     Iterate([=](AstNode *child) {
159         cb(child);
160         child->IterateRecursivelyPreorder(cb);
161     });
162 }
163 
IterateRecursivelyPostorder(const NodeTraverser & cb) const164 void AstNode::IterateRecursivelyPostorder(const NodeTraverser &cb) const
165 {
166     Iterate([=](AstNode *child) {
167         child->IterateRecursivelyPostorder(cb);
168         cb(child);
169     });
170 }
171 
AnyChildHelper(bool * found,const NodePredicate & cb,AstNode * ast)172 void AnyChildHelper(bool *found, const NodePredicate &cb, AstNode *ast)
173 {
174     if (*found) {
175         return;
176     }
177 
178     if (cb(ast)) {
179         *found = true;
180         return;
181     }
182 
183     ast->Iterate([=](AstNode *child) { AnyChildHelper(found, cb, child); });
184 }
185 
IsAnyChild(const NodePredicate & cb) const186 bool AstNode::IsAnyChild(const NodePredicate &cb) const
187 {
188     bool found = false;
189     Iterate([&found, cb](AstNode *child) { AnyChildHelper(&found, cb, child); });
190     return found;
191 }
192 
FindChildHelper(AstNode * & found,const NodePredicate & cb,AstNode * ast)193 void FindChildHelper(AstNode *&found, const NodePredicate &cb, AstNode *ast)
194 {
195     if (found != nullptr) {
196         return;
197     }
198 
199     if (cb(ast)) {
200         found = ast;
201         return;
202     }
203 
204     ast->Iterate([&found, cb](AstNode *child) { FindChildHelper(found, cb, child); });
205 }
206 
FindChild(const NodePredicate & cb) const207 AstNode *AstNode::FindChild(const NodePredicate &cb) const
208 {
209     AstNode *found = nullptr;
210     Iterate([&found, cb](AstNode *child) { FindChildHelper(found, cb, child); });
211     return found;
212 }
213 
EnclosingScope(const ir::AstNode * expr)214 varbinder::Scope *AstNode::EnclosingScope(const ir::AstNode *expr) noexcept
215 {
216     while (expr != nullptr && !expr->IsScopeBearer()) {
217         expr = expr->Parent();
218     }
219     return expr != nullptr ? expr->Scope() : nullptr;
220 }
221 
DumpJSON() const222 std::string AstNode::DumpJSON() const
223 {
224     ir::AstDumper dumper {this};
225     return dumper.Str();
226 }
227 
DumpEtsSrc() const228 std::string AstNode::DumpEtsSrc() const
229 {
230     ir::SrcDumper dumper {this};
231     return dumper.Str();
232 }
233 
DumpDecl() const234 std::string AstNode::DumpDecl() const
235 {
236     ir::SrcDumper dumper {this, true};
237     dumper.Run();
238     return dumper.Str();
239 }
240 
IsolatedDumpDecl() const241 std::string AstNode::IsolatedDumpDecl() const
242 {
243     ir::SrcDumper dumper {this, true, true};
244     dumper.Run();
245     return dumper.Str();
246 }
247 
SetOriginalNode(AstNode * originalNode)248 void AstNode::SetOriginalNode(AstNode *originalNode) noexcept
249 {
250     originalNode_ = originalNode;
251 }
252 
OriginalNode() const253 AstNode *AstNode::OriginalNode() const noexcept
254 {
255     return originalNode_;
256 }
257 
SetTransformedNode(std::string_view const transformationName,AstNode * transformedNode)258 void AstNode::SetTransformedNode(std::string_view const transformationName, AstNode *transformedNode)
259 {
260     transformedNode->SetOriginalNode(this);
261     transformedNode_ = std::make_optional(std::make_pair(transformationName, transformedNode));
262 }
263 
CleanUp()264 void AstNode::CleanUp()
265 {
266     SetVariable(nullptr);
267     if (IsScopeBearer()) {
268         ClearScope();
269     }
270     if (IsTyped()) {
271         this->AsTyped()->SetTsType(nullptr);
272     }
273 }
274 
IsReadonly() const275 bool AstNode::IsReadonly() const noexcept
276 {
277     return (flags_ & ModifierFlags::READONLY) != 0;
278 }
279 
280 // NOTE: For readonly parameter type
IsReadonlyType() const281 bool AstNode::IsReadonlyType() const noexcept
282 {
283     return (flags_ & ModifierFlags::READONLY_PARAMETER) != 0;
284 }
285 
IsOptionalDeclaration() const286 bool AstNode::IsOptionalDeclaration() const noexcept
287 {
288     return (flags_ & ModifierFlags::OPTIONAL) != 0;
289 }
290 
IsDefinite() const291 bool AstNode::IsDefinite() const noexcept
292 {
293     return (flags_ & ModifierFlags::DEFINITE) != 0;
294 }
295 
IsConstructor() const296 bool AstNode::IsConstructor() const noexcept
297 {
298     return (flags_ & ModifierFlags::CONSTRUCTOR) != 0;
299 }
300 
IsOverride() const301 bool AstNode::IsOverride() const noexcept
302 {
303     return (flags_ & ModifierFlags::OVERRIDE) != 0;
304 }
305 
ShallowClone(ArenaAllocator * allocator)306 AstNode *AstNode::ShallowClone(ArenaAllocator *allocator)
307 {
308     auto clone = Construct(allocator);
309     CopyTo(clone);
310     return clone;
311 }
312 
CopyTo(AstNode * other) const313 void AstNode::CopyTo(AstNode *other) const
314 {
315     ES2PANDA_ASSERT(other->type_ == type_);
316 
317     other->parent_ = parent_;
318     other->range_ = range_;
319     other->flags_ = flags_;
320     other->astNodeFlags_ = astNodeFlags_;
321     other->boxingUnboxingFlags_ = boxingUnboxingFlags_;
322     other->variable_ = variable_;
323     other->originalNode_ = originalNode_;
324     other->transformedNode_ = transformedNode_;
325 }
326 
Construct(ArenaAllocator * allocator)327 AstNode *AstNode::Construct([[maybe_unused]] ArenaAllocator *allocator)
328 {
329     ES2PANDA_UNREACHABLE();
330 }
331 }  // namespace ark::es2panda::ir
332