1/**
2 * Copyright (c) 2021 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_ASTNODE_H
17#define ES2PANDA_IR_ASTNODE_H
18
19#include <functional>
20#include <macros.h>
21
22#include <binder/binder.h>
23#include <binder/scope.h>
24#include <ir/astNodeMapping.h>
25#include <lexer/token/sourceLocation.h>
26#include <util/enumbitops.h>
27
28namespace panda::es2panda::compiler {
29class PandaGen;
30}  // namespace panda::es2panda::compiler
31
32namespace panda::es2panda::checker {
33class Checker;
34class Type;
35}  // namespace panda::es2panda::checker
36
37namespace panda::es2panda::ir {
38
39class AstNode;
40
41using NodeTraverser = std::function<void(AstNode *)>;
42
43using UpdateNodes = std::variant<AstNode *, std::vector<AstNode *>>;
44using NodeUpdater = std::function<UpdateNodes(AstNode *)>;
45
46enum class AstNodeType {
47#define DECLARE_NODE_TYPES(nodeType, className) nodeType,
48    AST_NODE_MAPPING(DECLARE_NODE_TYPES)
49#undef DECLARE_NODE_TYPES
50#define DECLARE_NODE_TYPES(nodeType1, nodeType2, baseClass, reinterpretClass) nodeType1, nodeType2,
51        AST_NODE_REINTERPRET_MAPPING(DECLARE_NODE_TYPES)
52#undef DECLARE_NODE_TYPES
53};
54
55enum class AstNodeFlags : uint8_t {
56    NO_OPTS = 0,
57    STRICT = (1U << 0U),
58    PARAMETER = (1U << 1U),
59};
60
61DEFINE_BITOPS(AstNodeFlags)
62
63enum class ModifierFlags : uint16_t {
64    NONE = 0,
65    STATIC = 1 << 0,
66    ASYNC = 1 << 1,
67    PUBLIC = 1 << 2,
68    PROTECTED = 1 << 3,
69    PRIVATE = 1 << 4,
70    DECLARE = 1 << 5,
71    READONLY = 1 << 6,
72    OPTIONAL = 1 << 7,
73    DEFINITE = 1 << 8,
74    ABSTRACT = 1 << 9,
75    ACCESSOR = 1 << 10,
76    OVERRIDE = 1 << 11,
77    ACCESS = PUBLIC | PROTECTED | PRIVATE,
78    ALL = STATIC | ASYNC | ACCESS | DECLARE | READONLY | ABSTRACT | ACCESSOR | OVERRIDE,
79    ALLOWED_IN_CTOR_PARAMETER = ACCESS | READONLY | OVERRIDE,
80};
81
82DEFINE_BITOPS(ModifierFlags)
83
84enum class ScriptFunctionFlags : uint16_t {
85    NONE = 0,
86    GENERATOR = 1 << 0,
87    ASYNC = 1 << 1,
88    ARROW = 1 << 2,
89    EXPRESSION = 1 << 3,
90    OVERLOAD = 1 << 4,
91    CONSTRUCTOR = 1 << 5,
92    METHOD = 1 << 6,
93    CONCURRENT = 1 << 7,
94    STATIC_INITIALIZER = 1 << 8,
95    INSTANCE_INITIALIZER = 1 << 9,
96    GENERATED_CONSTRUCTOR = 1 << 10,
97    SENDABLE = 1 << 11,
98};
99
100DEFINE_BITOPS(ScriptFunctionFlags)
101
102enum class TSOperatorType { READONLY, KEYOF, UNIQUE };
103enum class MappedOption { NO_OPTS, PLUS, MINUS };
104
105// Predefinitions
106class AstDumper;
107class Expression;
108class Statement;
109
110#define DECLARE_CLASSES(nodeType, className) class className;
111AST_NODE_MAPPING(DECLARE_CLASSES)
112#undef DECLARE_CLASSES
113
114#define DECLARE_CLASSES(nodeType1, nodeType2, baseClass, reinterpretClass) class baseClass;
115AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES)
116#undef DECLARE_CLASSES
117
118class AstNode {
119public:
120    explicit AstNode(AstNodeType type) : type_(type) {};
121    virtual ~AstNode() = default;
122    NO_COPY_SEMANTIC(AstNode);
123    NO_MOVE_SEMANTIC(AstNode);
124
125    bool IsProgram() const
126    {
127        return parent_ == nullptr;
128    }
129
130#define DECLARE_IS_CHECKS(nodeType, className) \
131    bool Is##className() const                 \
132    {                                          \
133        return type_ == AstNodeType::nodeType; \
134    }
135    AST_NODE_MAPPING(DECLARE_IS_CHECKS)
136#undef DECLARE_IS_CHECKS
137
138#define DECLARE_IS_CHECKS(nodeType1, nodeType2, baseClass, reinterpretClass) \
139    bool Is##baseClass() const                                               \
140    {                                                                        \
141        return type_ == AstNodeType::nodeType1;                              \
142    }                                                                        \
143    bool Is##reinterpretClass() const                                        \
144    {                                                                        \
145        return type_ == AstNodeType::nodeType2;                              \
146    }
147    AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS)
148#undef DECLARE_IS_CHECKS
149
150    virtual bool IsStatement() const
151    {
152        return false;
153    }
154
155    virtual bool IsExpression() const
156    {
157        return false;
158    }
159
160#define DECLARE_AS_CASTS(nodeType, className)             \
161    className *As##className()                            \
162    {                                                     \
163        ASSERT(Is##className());                          \
164        return reinterpret_cast<className *>(this);       \
165    }                                                     \
166    const className *As##className() const                \
167    {                                                     \
168        ASSERT(Is##className());                          \
169        return reinterpret_cast<const className *>(this); \
170    }
171    AST_NODE_MAPPING(DECLARE_AS_CASTS)
172#undef DECLARE_AS_CASTS
173
174#define DECLARE_AS_CASTS(nodeType1, nodeType2, baseClass, reinterpretClass) \
175    baseClass *As##baseClass()                                              \
176    {                                                                       \
177        ASSERT(Is##baseClass());                                            \
178        return reinterpret_cast<baseClass *>(this);                         \
179    }                                                                       \
180    baseClass *As##reinterpretClass()                                       \
181    {                                                                       \
182        ASSERT(Is##reinterpretClass());                                     \
183        return reinterpret_cast<baseClass *>(this);                         \
184    }                                                                       \
185    const baseClass *As##baseClass() const                                  \
186    {                                                                       \
187        ASSERT(Is##baseClass());                                            \
188        return reinterpret_cast<const baseClass *>(this);                   \
189    }                                                                       \
190    const baseClass *As##reinterpretClass() const                           \
191    {                                                                       \
192        ASSERT(Is##reinterpretClass());                                     \
193        return reinterpret_cast<const baseClass *>(this);                   \
194    }
195    AST_NODE_REINTERPRET_MAPPING(DECLARE_AS_CASTS)
196#undef DECLARE_AS_CASTS
197
198    Expression *AsExpression()
199    {
200        ASSERT(IsExpression());
201        return reinterpret_cast<Expression *>(this);
202    }
203
204    const Expression *AsExpression() const
205    {
206        ASSERT(IsExpression());
207        return reinterpret_cast<const Expression *>(this);
208    }
209
210    Statement *AsStatement()
211    {
212        ASSERT(IsStatement());
213        return reinterpret_cast<Statement *>(this);
214    }
215
216    const Statement *AsStatement() const
217    {
218        ASSERT(IsStatement());
219        return reinterpret_cast<const Statement *>(this);
220    }
221
222    void SetRange(const lexer::SourceRange &loc)
223    {
224        range_ = loc;
225    }
226
227    void SetStart(const lexer::SourcePosition &start)
228    {
229        range_.start = start;
230    }
231
232    void SetEnd(const lexer::SourcePosition &end)
233    {
234        range_.end = end;
235    }
236
237    const lexer::SourcePosition &Start() const
238    {
239        return range_.start;
240    }
241
242    const lexer::SourcePosition &End() const
243    {
244        return range_.end;
245    }
246
247    const lexer::SourceRange &Range() const
248    {
249        return range_;
250    }
251
252    AstNodeType Type() const
253    {
254        return type_;
255    }
256
257    AstNode *Parent()
258    {
259        return const_cast<AstNode*>(parent_);
260    }
261
262    const AstNode *Parent() const
263    {
264        return parent_;
265    }
266
267    void SetParent(const AstNode *parent)
268    {
269        parent_ = parent;
270    }
271
272    const AstNode *Original() const
273    {
274        return original_;
275    }
276
277    void SetOriginal(const AstNode *original)
278    {
279        original_ = original;
280    }
281
282    binder::Variable *Variable() const
283    {
284        return variable_;
285    }
286
287    void SetVariable(binder::Variable *variable)
288    {
289        variable_ = variable;
290    }
291
292    virtual void Iterate(const NodeTraverser &cb) const = 0;
293    virtual void Dump(ir::AstDumper *dumper) const = 0;
294    virtual void Compile([[maybe_unused]] compiler::PandaGen *pg) const = 0;
295    virtual checker::Type *Check([[maybe_unused]] checker::Checker *checker) const = 0;
296    virtual void UpdateSelf([[maybe_unused]] const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) = 0;
297
298protected:
299    void SetType(AstNodeType type)
300    {
301        type_ = type;
302    }
303
304    const AstNode *parent_ {};
305    lexer::SourceRange range_ {};
306    AstNodeType type_;
307    binder::Variable *variable_ {nullptr};
308    const AstNode *original_ {nullptr};
309};
310
311}  // namespace panda::es2panda::ir
312#endif
313