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