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 20namespace ark::es2panda::ir { 21 22AstNode::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 70bool AstNode::IsScopeBearer() const noexcept 71{ 72 return false; 73} 74 75varbinder::Scope *AstNode::Scope() const noexcept 76{ 77 UNREACHABLE(); 78} 79 80void AstNode::ClearScope() noexcept 81{ 82 UNREACHABLE(); 83} 84 85ir::ClassElement *AstNode::AsClassElement() 86{ 87 ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock()); 88 return reinterpret_cast<ir::ClassElement *>(this); 89} 90 91const ir::ClassElement *AstNode::AsClassElement() const 92{ 93 ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock()); 94 return reinterpret_cast<const ir::ClassElement *>(this); 95} 96 97template <typename R, typename T> 98static 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 109ir::BlockStatement *AstNode::GetTopStatement() 110{ 111 return GetTopStatementImpl<ir::BlockStatement *>(this); 112} 113 114const ir::BlockStatement *AstNode::GetTopStatement() const 115{ 116 return GetTopStatementImpl<const ir::BlockStatement *>(this); 117} 118 119AstNode *AstNode::Clone([[maybe_unused]] ArenaAllocator *const allocator, [[maybe_unused]] AstNode *const parent) 120{ 121 UNREACHABLE(); 122} 123 124void 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 129void 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 140void 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 150void AstNode::IterateRecursively(const NodeTraverser &cb) const 151{ // pre-order, use when you don't care 152 IterateRecursivelyPreorder(cb); 153} 154 155void AstNode::IterateRecursivelyPreorder(const NodeTraverser &cb) const 156{ 157 Iterate([=](AstNode *child) { 158 cb(child); 159 child->IterateRecursivelyPreorder(cb); 160 }); 161} 162 163void AstNode::IterateRecursivelyPostorder(const NodeTraverser &cb) const 164{ 165 Iterate([=](AstNode *child) { 166 child->IterateRecursivelyPostorder(cb); 167 cb(child); 168 }); 169} 170 171void 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 185bool 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 192void 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 206AstNode *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 213varbinder::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 221std::string AstNode::DumpJSON() const 222{ 223 ir::AstDumper dumper {this}; 224 return dumper.Str(); 225} 226 227std::string AstNode::DumpEtsSrc() const 228{ 229 ir::SrcDumper dumper {this}; 230 return dumper.Str(); 231} 232 233void AstNode::SetOriginalNode(AstNode *originalNode) 234{ 235 originalNode_ = originalNode; 236} 237 238void 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