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