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