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 "astNode.h"
17 #include "ir/astDump.h"
18 #include "ir/srcDump.h"
19
20 namespace ark::es2panda::ir {
21
AstNode(AstNode const &other)22 AstNode::AstNode(AstNode const &other)
23 {
24 range_ = other.range_;
25 type_ = other.type_;
26 if (other.variable_ != nullptr) {
27 variable_ = other.variable_;
28 }
29 flags_ = other.flags_;
30 astNodeFlags_ = other.astNodeFlags_;
31 // boxing_unboxing_flags_ {}; leave default value!
32 }
33
34 [[nodiscard]] bool AstNode::IsExported() const noexcept
35 {
36 if (UNLIKELY(IsClassDefinition())) {
37 return parent_->IsExported();
38 }
39
40 return (flags_ & ModifierFlags::EXPORT) != 0;
41 }
42
43 [[nodiscard]] bool AstNode::IsDefaultExported() const noexcept
44 {
45 if (UNLIKELY(IsClassDefinition())) {
46 return parent_->IsDefaultExported();
47 }
48
49 return (flags_ & ModifierFlags::DEFAULT_EXPORT) != 0;
50 }
51
52 [[nodiscard]] bool AstNode::IsExportedType() const noexcept
53 {
54 if (UNLIKELY(IsClassDefinition())) {
55 return this->parent_->IsExportedType();
56 }
57
58 return (flags_ & ModifierFlags::EXPORT_TYPE) != 0;
59 }
60
61 [[nodiscard]] bool AstNode::HasExportAlias() const noexcept
62 {
63 if (UNLIKELY(IsClassDefinition())) {
64 return parent_->HasExportAlias();
65 }
66
67 return (astNodeFlags_ & AstNodeFlags::HAS_EXPORT_ALIAS) != 0;
68 }
69
70 bool AstNode::IsScopeBearer() const noexcept
71 {
72 return false;
73 }
74
75 varbinder::Scope *AstNode::Scope() const noexcept
76 {
77 UNREACHABLE();
78 }
79
80 void AstNode::ClearScope() noexcept
81 {
82 UNREACHABLE();
83 }
84
AsClassElement()85 ir::ClassElement *AstNode::AsClassElement()
86 {
87 ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock());
88 return reinterpret_cast<ir::ClassElement *>(this);
89 }
90
AsClassElement() const91 const ir::ClassElement *AstNode::AsClassElement() const
92 {
93 ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock());
94 return reinterpret_cast<const ir::ClassElement *>(this);
95 }
96
97 template <typename R, typename T>
GetTopStatementImpl(T *self)98 static R GetTopStatementImpl(T *self)
99 {
100 auto iter = self;
101
102 while (iter->Parent()) {
103 iter = iter->Parent();
104 }
105
106 return reinterpret_cast<R>(iter);
107 }
108
GetTopStatement()109 ir::BlockStatement *AstNode::GetTopStatement()
110 {
111 return GetTopStatementImpl<ir::BlockStatement *>(this);
112 }
113
GetTopStatement() const114 const ir::BlockStatement *AstNode::GetTopStatement() const
115 {
116 return GetTopStatementImpl<const ir::BlockStatement *>(this);
117 }
118
Clone([[maybe_unused]] ArenaAllocator *const allocator, [[maybe_unused]] AstNode *const parent)119 AstNode *AstNode::Clone([[maybe_unused]] ArenaAllocator *const allocator, [[maybe_unused]] AstNode *const parent)
120 {
121 UNREACHABLE();
122 }
123
TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName)124 void AstNode::TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName)
125 { // post-order, but use when you don't care about the order
126 TransformChildrenRecursivelyPostorder(cb, transformationName);
127 }
128
TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName)129 void AstNode::TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName)
130 {
131 TransformChildren(
132 [=](AstNode *child) {
133 auto *res = cb(child);
134 res->TransformChildrenRecursivelyPreorder(cb, transformationName);
135 return res;
136 },
137 transformationName);
138 }
139
TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName)140 void AstNode::TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName)
141 {
142 TransformChildren(
143 [=](AstNode *child) {
144 child->TransformChildrenRecursivelyPostorder(cb, transformationName);
145 return cb(child);
146 },
147 transformationName);
148 }
149
IterateRecursively(const NodeTraverser &cb) const150 void AstNode::IterateRecursively(const NodeTraverser &cb) const
151 { // pre-order, use when you don't care
152 IterateRecursivelyPreorder(cb);
153 }
154
IterateRecursivelyPreorder(const NodeTraverser &cb) const155 void AstNode::IterateRecursivelyPreorder(const NodeTraverser &cb) const
156 {
157 Iterate([=](AstNode *child) {
158 cb(child);
159 child->IterateRecursivelyPreorder(cb);
160 });
161 }
162
IterateRecursivelyPostorder(const NodeTraverser &cb) const163 void AstNode::IterateRecursivelyPostorder(const NodeTraverser &cb) const
164 {
165 Iterate([=](AstNode *child) {
166 child->IterateRecursivelyPostorder(cb);
167 cb(child);
168 });
169 }
170
AnyChildHelper(bool *found, const NodePredicate &cb, AstNode *ast)171 void AnyChildHelper(bool *found, const NodePredicate &cb, AstNode *ast)
172 {
173 if (*found) {
174 return;
175 }
176
177 if (cb(ast)) {
178 *found = true;
179 return;
180 }
181
182 ast->Iterate([=](AstNode *child) { AnyChildHelper(found, cb, child); });
183 }
184
IsAnyChild(const NodePredicate &cb) const185 bool AstNode::IsAnyChild(const NodePredicate &cb) const
186 {
187 bool found = false;
188 Iterate([&found, cb](AstNode *child) { AnyChildHelper(&found, cb, child); });
189 return found;
190 }
191
FindChildHelper(AstNode *&found, const NodePredicate &cb, AstNode *ast)192 void FindChildHelper(AstNode *&found, const NodePredicate &cb, AstNode *ast)
193 {
194 if (found != nullptr) {
195 return;
196 }
197
198 if (cb(ast)) {
199 found = ast;
200 return;
201 }
202
203 ast->Iterate([&found, cb](AstNode *child) { FindChildHelper(found, cb, child); });
204 }
205
FindChild(const NodePredicate &cb) const206 AstNode *AstNode::FindChild(const NodePredicate &cb) const
207 {
208 AstNode *found = nullptr;
209 Iterate([&found, cb](AstNode *child) { FindChildHelper(found, cb, child); });
210 return found;
211 }
212
EnclosingScope(const ir::AstNode *expr)213 varbinder::Scope *AstNode::EnclosingScope(const ir::AstNode *expr)
214 {
215 while (expr != nullptr && !expr->IsScopeBearer()) {
216 expr = expr->Parent();
217 }
218 return expr != nullptr ? expr->Scope() : nullptr;
219 }
220
DumpJSON() const221 std::string AstNode::DumpJSON() const
222 {
223 ir::AstDumper dumper {this};
224 return dumper.Str();
225 }
226
DumpEtsSrc() const227 std::string AstNode::DumpEtsSrc() const
228 {
229 ir::SrcDumper dumper {this};
230 return dumper.Str();
231 }
232
SetOriginalNode(AstNode *originalNode)233 void AstNode::SetOriginalNode(AstNode *originalNode)
234 {
235 originalNode_ = originalNode;
236 }
237
SetTransformedNode(std::string_view const transformationName, AstNode *transformedNode)238 void AstNode::SetTransformedNode(std::string_view const transformationName, AstNode *transformedNode)
239 {
240 ASSERT(!transformedNode_.has_value());
241 transformedNode->SetOriginalNode(this);
242 transformedNode_ = std::make_optional(std::make_pair(transformationName, transformedNode));
243 }
244 } // namespace ark::es2panda::ir
245