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