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 #ifndef ES2PANDA_IR_AST_NODE_H 17 #define ES2PANDA_IR_AST_NODE_H 18 19 #include "astNodeFlags.h" 20 #include "astNodeMapping.h" 21 #include "ir/visitor/AstVisitor.h" 22 #include "lexer/token/sourceLocation.h" 23 #include "macros.h" 24 25 namespace ark::es2panda::compiler { 26 class PandaGen; 27 class ETSGen; 28 } // namespace ark::es2panda::compiler 29 30 namespace ark::es2panda::checker { 31 class TSChecker; 32 class ETSChecker; 33 class Type; 34 } // namespace ark::es2panda::checker 35 36 namespace ark::es2panda::varbinder { 37 class Variable; 38 class Scope; 39 } // namespace ark::es2panda::varbinder 40 41 namespace ark::es2panda::ir { 42 // NOLINTBEGIN(modernize-avoid-c-arrays) 43 inline constexpr char const CLONE_ALLOCATION_ERROR[] = "Unsuccessful allocation during cloning."; 44 // NOLINTEND(modernize-avoid-c-arrays) 45 46 class AstNode; 47 class TypeNode; 48 49 using NodeTransformer = std::function<AstNode *(AstNode *)>; 50 using NodeTraverser = std::function<void(AstNode *)>; 51 using NodePredicate = std::function<bool(AstNode *)>; 52 53 enum class AstNodeType { 54 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 55 #define DECLARE_NODE_TYPES(nodeType, className) nodeType, 56 AST_NODE_MAPPING(DECLARE_NODE_TYPES) 57 #undef DECLARE_NODE_TYPES 58 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 59 #define DECLARE_NODE_TYPES(nodeType1, nodeType2, baseClass, reinterpretClass) nodeType1, nodeType2, 60 AST_NODE_REINTERPRET_MAPPING(DECLARE_NODE_TYPES) 61 #undef DECLARE_NODE_TYPES 62 }; 63 64 // Forward declarations 65 class AstDumper; 66 class Expression; 67 class SrcDumper; 68 class Statement; 69 class ClassElement; 70 template <typename T> 71 class Typed; 72 73 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 74 #define DECLARE_CLASSES(nodeType, className) class className; 75 AST_NODE_MAPPING(DECLARE_CLASSES) 76 #undef DECLARE_CLASSES 77 78 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 79 #define DECLARE_CLASSES(nodeType1, nodeType2, baseClass, reinterpretClass) class baseClass; 80 AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES) 81 #undef DECLARE_CLASSES 82 83 class AstNode { 84 public: AstNode(AstNodeType type)85 explicit AstNode(AstNodeType type) : type_(type) {}; AstNode(AstNodeType type, ModifierFlags flags)86 explicit AstNode(AstNodeType type, ModifierFlags flags) : type_(type), flags_(flags) {}; 87 virtual ~AstNode() = default; 88 89 AstNode() = delete; 90 NO_MOVE_SEMANTIC(AstNode); 91 IsProgram() const92 bool IsProgram() const 93 { 94 return parent_ == nullptr; 95 } 96 97 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 98 #define DECLARE_IS_CHECKS(nodeType, className) \ 99 bool Is##className() const \ 100 { \ 101 return type_ == AstNodeType::nodeType; \ 102 } 103 AST_NODE_MAPPING(DECLARE_IS_CHECKS) 104 #undef DECLARE_IS_CHECKS 105 106 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 107 #define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \ 108 bool Is##baseClass() const \ 109 { \ 110 return type_ == AstNodeType::nodeType1; \ 111 } \ 112 bool Is##reinterpretClass() const \ 113 { \ 114 return type_ == AstNodeType::nodeType2; \ 115 } 116 AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS) 117 #undef DECLARE_IS_CHECKS 118 119 [[nodiscard]] virtual bool IsStatement() const noexcept 120 { 121 return false; 122 } 123 124 [[nodiscard]] virtual bool IsExpression() const noexcept 125 { 126 return false; 127 } 128 IsTyped() const129 virtual bool IsTyped() const 130 { 131 return false; 132 } 133 AsTyped()134 Typed<AstNode> *AsTyped() 135 { 136 ASSERT(IsTyped()); 137 return reinterpret_cast<Typed<AstNode> *>(this); 138 } 139 AsTyped() const140 Typed<AstNode> const *AsTyped() const 141 { 142 ASSERT(IsTyped()); 143 return reinterpret_cast<Typed<AstNode> const *>(this); 144 } 145 146 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 147 #define DECLARE_AS_CASTS(nodeType, className) \ 148 className *As##className() \ 149 { \ 150 ASSERT(Is##className()); \ 151 return reinterpret_cast<className *>(this); \ 152 } \ 153 const className *As##className() const \ 154 { \ 155 ASSERT(Is##className()); \ 156 return reinterpret_cast<const className *>(this); \ 157 } 158 AST_NODE_MAPPING(DECLARE_AS_CASTS) 159 #undef DECLARE_AS_CASTS 160 161 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 162 #define DECLARE_AS_CASTS(nodeType1, nodeType2, baseClass, reinterpretClass) \ 163 baseClass *As##baseClass() \ 164 { \ 165 ASSERT(Is##baseClass()); \ 166 return reinterpret_cast<baseClass *>(this); \ 167 } \ 168 baseClass *As##reinterpretClass() \ 169 { \ 170 ASSERT(Is##reinterpretClass()); \ 171 return reinterpret_cast<baseClass *>(this); \ 172 } \ 173 const baseClass *As##baseClass() const \ 174 { \ 175 ASSERT(Is##baseClass()); \ 176 return reinterpret_cast<const baseClass *>(this); \ 177 } \ 178 const baseClass *As##reinterpretClass() const \ 179 { \ 180 ASSERT(Is##reinterpretClass()); \ 181 return reinterpret_cast<const baseClass *>(this); \ 182 } 183 AST_NODE_REINTERPRET_MAPPING(DECLARE_AS_CASTS) 184 #undef DECLARE_AS_CASTS 185 AsExpression()186 Expression *AsExpression() 187 { 188 ASSERT(IsExpression()); 189 return reinterpret_cast<Expression *>(this); 190 } 191 AsExpression() const192 const Expression *AsExpression() const 193 { 194 ASSERT(IsExpression()); 195 return reinterpret_cast<const Expression *>(this); 196 } 197 AsStatement()198 Statement *AsStatement() 199 { 200 ASSERT(IsStatement()); 201 return reinterpret_cast<Statement *>(this); 202 } 203 AsStatement() const204 const Statement *AsStatement() const 205 { 206 ASSERT(IsStatement()); 207 return reinterpret_cast<const Statement *>(this); 208 } 209 210 void SetRange(const lexer::SourceRange &loc) noexcept 211 { 212 range_ = loc; 213 } 214 215 void SetStart(const lexer::SourcePosition &start) noexcept 216 { 217 range_.start = start; 218 } 219 220 void SetEnd(const lexer::SourcePosition &end) noexcept 221 { 222 range_.end = end; 223 } 224 225 [[nodiscard]] const lexer::SourcePosition &Start() const noexcept 226 { 227 return range_.start; 228 } 229 230 [[nodiscard]] const lexer::SourcePosition &End() const noexcept 231 { 232 return range_.end; 233 } 234 235 [[nodiscard]] const lexer::SourceRange &Range() const noexcept 236 { 237 return range_; 238 } 239 240 [[nodiscard]] AstNodeType Type() const noexcept 241 { 242 return type_; 243 } 244 245 [[nodiscard]] AstNode *Parent() noexcept 246 { 247 return parent_; 248 } 249 250 [[nodiscard]] const AstNode *Parent() const noexcept 251 { 252 return parent_; 253 } 254 255 void SetParent(AstNode *const parent) noexcept 256 { 257 parent_ = parent; 258 } 259 260 [[nodiscard]] varbinder::Variable *Variable() const noexcept 261 { 262 return variable_; 263 } 264 265 void SetVariable(varbinder::Variable *variable) noexcept 266 { 267 variable_ = variable; 268 } 269 270 // When no decorators are allowed, we cannot return a reference to an empty vector. DecoratorsPtr() const271 virtual const ArenaVector<ir::Decorator *> *DecoratorsPtr() const 272 { 273 return nullptr; 274 } 275 AddDecorators([[maybe_unused]] ArenaVector<ir::Decorator *> &&decorators)276 virtual void AddDecorators([[maybe_unused]] ArenaVector<ir::Decorator *> &&decorators) 277 { 278 UNREACHABLE(); 279 } 280 CanHaveDecorator([[maybe_unused]] bool inTs) const281 virtual bool CanHaveDecorator([[maybe_unused]] bool inTs) const 282 { 283 return false; 284 } 285 286 [[nodiscard]] bool IsReadonly() const noexcept 287 { 288 return (flags_ & ModifierFlags::READONLY) != 0; 289 } 290 291 [[nodiscard]] bool IsOptionalDeclaration() const noexcept 292 { 293 return (flags_ & ModifierFlags::OPTIONAL) != 0; 294 } 295 296 [[nodiscard]] bool IsDefinite() const noexcept 297 { 298 return (flags_ & ModifierFlags::DEFINITE) != 0; 299 } 300 301 [[nodiscard]] bool IsConstructor() const noexcept 302 { 303 return (flags_ & ModifierFlags::CONSTRUCTOR) != 0; 304 } 305 306 [[nodiscard]] bool IsOverride() const noexcept 307 { 308 return (flags_ & ModifierFlags::OVERRIDE) != 0; 309 } 310 311 void SetOverride() noexcept 312 { 313 flags_ |= ModifierFlags::OVERRIDE; 314 } 315 316 [[nodiscard]] bool IsAsync() const noexcept 317 { 318 return (flags_ & ModifierFlags::ASYNC) != 0; 319 } 320 321 [[nodiscard]] bool IsSynchronized() const noexcept 322 { 323 return (flags_ & ModifierFlags::SYNCHRONIZED) != 0; 324 } 325 326 [[nodiscard]] bool IsNative() const noexcept 327 { 328 return (flags_ & ModifierFlags::NATIVE) != 0; 329 } 330 331 [[nodiscard]] bool IsConst() const noexcept 332 { 333 return (flags_ & ModifierFlags::CONST) != 0; 334 } 335 336 [[nodiscard]] bool IsStatic() const noexcept 337 { 338 return (flags_ & ModifierFlags::STATIC) != 0; 339 } 340 341 [[nodiscard]] bool IsFinal() const noexcept 342 { 343 return (flags_ & ModifierFlags::FINAL) != 0U; 344 } 345 346 [[nodiscard]] bool IsAbstract() const noexcept 347 { 348 return (flags_ & ModifierFlags::ABSTRACT) != 0; 349 } 350 351 [[nodiscard]] bool IsPublic() const noexcept 352 { 353 return (flags_ & ModifierFlags::PUBLIC) != 0; 354 } 355 356 [[nodiscard]] bool IsProtected() const noexcept 357 { 358 return (flags_ & ModifierFlags::PROTECTED) != 0; 359 } 360 361 [[nodiscard]] bool IsPrivate() const noexcept 362 { 363 return (flags_ & ModifierFlags::PRIVATE) != 0; 364 } 365 366 [[nodiscard]] bool IsInternal() const noexcept 367 { 368 return (flags_ & ModifierFlags::INTERNAL) != 0; 369 } 370 371 [[nodiscard]] bool IsExported() const noexcept; 372 373 [[nodiscard]] bool IsDefaultExported() const noexcept; 374 375 [[nodiscard]] bool IsExportedType() const noexcept; 376 377 [[nodiscard]] bool IsDeclare() const noexcept 378 { 379 return (flags_ & ModifierFlags::DECLARE) != 0; 380 } 381 382 [[nodiscard]] bool IsIn() const noexcept 383 { 384 return (flags_ & ModifierFlags::IN) != 0; 385 } 386 387 [[nodiscard]] bool IsOut() const noexcept 388 { 389 return (flags_ & ModifierFlags::OUT) != 0; 390 } 391 392 [[nodiscard]] bool IsSetter() const noexcept 393 { 394 return (flags_ & ModifierFlags::SETTER) != 0; 395 } 396 397 void AddModifier(ModifierFlags const flags) noexcept 398 { 399 flags_ |= flags; 400 } 401 402 void ClearModifier(ModifierFlags const flags) noexcept 403 { 404 flags_ &= ~flags; 405 } 406 407 [[nodiscard]] ModifierFlags Modifiers() noexcept 408 { 409 return flags_; 410 } 411 412 [[nodiscard]] ModifierFlags Modifiers() const noexcept 413 { 414 return flags_; 415 } 416 417 [[nodiscard]] bool HasExportAlias() const noexcept; 418 419 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 420 #define DECLARE_FLAG_OPERATIONS(flag_type, member_name) \ 421 void Set##flag_type(flag_type flags) const noexcept \ 422 { \ 423 (member_name) = flags; \ 424 } \ 425 \ 426 void Add##flag_type(flag_type flag) const noexcept \ 427 { \ 428 (member_name) |= flag; \ 429 } \ 430 \ 431 [[nodiscard]] flag_type Get##flag_type() const noexcept \ 432 { \ 433 return (member_name); \ 434 } \ 435 \ 436 bool Has##flag_type(flag_type flag) const noexcept \ 437 { \ 438 return ((member_name)&flag) != 0U; \ 439 } \ 440 void Remove##flag_type(flag_type flag) const noexcept \ 441 { \ 442 (member_name) &= ~flag; \ 443 } 444 445 DECLARE_FLAG_OPERATIONS(BoxingUnboxingFlags, boxingUnboxingFlags_); 446 DECLARE_FLAG_OPERATIONS(AstNodeFlags, astNodeFlags_); 447 #undef DECLARE_FLAG_OPERATIONS 448 449 ir::ClassElement *AsClassElement(); 450 const ir::ClassElement *AsClassElement() const; 451 452 static varbinder::Scope *EnclosingScope(const ir::AstNode *expr); 453 454 [[nodiscard]] virtual bool IsScopeBearer() const noexcept; 455 [[nodiscard]] virtual varbinder::Scope *Scope() const noexcept; 456 457 virtual void ClearScope() noexcept; 458 459 [[nodiscard]] ir::BlockStatement *GetTopStatement(); 460 [[nodiscard]] const ir::BlockStatement *GetTopStatement() const; 461 462 [[nodiscard]] virtual AstNode *Clone(ArenaAllocator *const allocator, AstNode *const parent); 463 464 virtual void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) = 0; 465 virtual void Iterate(const NodeTraverser &cb) const = 0; 466 467 void TransformChildrenRecursively(const NodeTransformer &cb, std::string_view transformationName); 468 void TransformChildrenRecursivelyPreorder(const NodeTransformer &cb, std::string_view transformationName); 469 void TransformChildrenRecursivelyPostorder(const NodeTransformer &cb, std::string_view transformationName); 470 471 void IterateRecursively(const NodeTraverser &cb) const; 472 void IterateRecursivelyPreorder(const NodeTraverser &cb) const; 473 void IterateRecursivelyPostorder(const NodeTraverser &cb) const; 474 475 bool IsAnyChild(const NodePredicate &cb) const; 476 AstNode *FindChild(const NodePredicate &cb) const; 477 478 std::string DumpJSON() const; 479 std::string DumpEtsSrc() const; 480 481 virtual void Dump(ir::AstDumper *dumper) const = 0; 482 virtual void Dump(ir::SrcDumper *dumper) const = 0; 483 virtual void Compile([[maybe_unused]] compiler::PandaGen *pg) const = 0; Compile([[maybe_unused]] compiler::ETSGen *etsg) const484 virtual void Compile([[maybe_unused]] compiler::ETSGen *etsg) const {}; 485 virtual checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) = 0; 486 virtual checker::Type *Check([[maybe_unused]] checker::ETSChecker *checker) = 0; 487 488 void SetTransformedNode(std::string_view transformationName, AstNode *transformedNode); 489 490 using ASTVisitorT = visitor::ASTAbstractVisitor; 491 492 virtual void Accept(ASTVisitorT *v) = 0; 493 494 /** 495 * On each node you should implement: 496 * void accept(AV* v) override { 497 * ASTVisitorT::accept(this, v); 498 * } 499 */ 500 void SetOriginalNode(AstNode *originalNode); 501 502 protected: 503 AstNode(AstNode const &other); 504 505 void SetType(AstNodeType const type) noexcept 506 { 507 type_ = type; 508 } 509 510 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 511 AstNode *parent_ {}; 512 lexer::SourceRange range_ {}; 513 AstNodeType type_; 514 ModifierFlags flags_ {}; 515 mutable AstNodeFlags astNodeFlags_ {}; 516 mutable BoxingUnboxingFlags boxingUnboxingFlags_ {}; 517 // NOLINTEND(misc-non-private-member-variables-in-classes) 518 519 private: 520 AstNode &operator=(const AstNode &) = default; 521 522 varbinder::Variable *variable_ {}; 523 AstNode *originalNode_ = nullptr; 524 // {lowering_phase_name, new_generated_node} 525 std::optional<std::pair<std::string_view, AstNode *>> transformedNode_ = std::nullopt; 526 }; 527 528 template <typename T> 529 class Annotated : public T { 530 public: 531 Annotated() = delete; 532 ~Annotated() override = default; 533 534 NO_COPY_OPERATOR(Annotated); 535 NO_MOVE_SEMANTIC(Annotated); 536 537 [[nodiscard]] TypeNode *TypeAnnotation() const noexcept 538 { 539 return typeAnnotation_; 540 } 541 542 void SetTsTypeAnnotation(TypeNode *const typeAnnotation) noexcept 543 { 544 typeAnnotation_ = typeAnnotation; 545 } 546 547 protected: Annotated(AstNodeType const type, TypeNode *const typeAnnotation)548 explicit Annotated(AstNodeType const type, TypeNode *const typeAnnotation) 549 : T(type), typeAnnotation_(typeAnnotation) 550 { 551 } Annotated(AstNodeType const type)552 explicit Annotated(AstNodeType const type) : T(type) {} Annotated(AstNodeType const type, ModifierFlags const flags)553 explicit Annotated(AstNodeType const type, ModifierFlags const flags) : T(type, flags) {} 554 Annotated(Annotated const &other)555 Annotated(Annotated const &other) : T(static_cast<T const &>(other)) {} 556 557 private: 558 TypeNode *typeAnnotation_ {}; 559 }; 560 561 } // namespace ark::es2panda::ir 562 #endif 563