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