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