• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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