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