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_COMPILER_CHECKER_ETS_ASSIGN_ANALYZER_H
17#define ES2PANDA_COMPILER_CHECKER_ETS_ASSIGN_ANALYZER_H
18
19#include "checker/ETSchecker.h"
20#include "checker/ets/baseAnalyzer.h"
21
22#include "utils/arena_containers.h"
23
24namespace ark::es2panda::ir {
25class AstNode;
26}  // namespace ark::es2panda::ir
27
28namespace ark::es2panda::checker {
29
30class Set {
31public:
32    Set() = default;
33    ~Set() = default;
34
35    DEFAULT_COPY_SEMANTIC(Set);
36    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(Set);
37
38    void Reset();
39    bool IsReset();
40    void Incl(const int id);
41    void InclRange(const int start, const int limit);
42    void ExcludeFrom(const int start);
43    void Excl(const int id);
44    bool IsMember(const int id) const;
45    Set &AndSet(const Set &xs);
46    Set &OrSet(const Set &xs);
47    Set &DiffSet(const Set &xs);
48    int Next(const int id);
49
50protected:
51    void InternalAndSet(const Set &xs);
52
53private:
54    bool reset_ {};
55    std::set<int> nodes_ {};
56};
57
58class AssignPendingExit : public PendingExit {
59public:
60    explicit AssignPendingExit(const ir::AstNode *node, Set &inits, Set &uninits)
61        : PendingExit(node), inits_(&inits), uninits_(&uninits)
62    {
63        exitInits_ = inits;
64        exitUninits_ = uninits;
65    }
66    ~AssignPendingExit() override = default;
67
68    DEFAULT_COPY_SEMANTIC(AssignPendingExit);
69    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(AssignPendingExit);
70
71    void ResolveJump() override
72    {
73        inits_->AndSet(exitInits_);
74        uninits_->AndSet(exitUninits_);
75    }
76
77    // NOLINTBEGIN(misc-non-private-member-variables-in-classes,readability-identifier-naming)
78    Set *inits_;
79    Set *uninits_;
80    Set exitInits_;
81    Set exitUninits_;
82    // NOLINTEND(misc-non-private-member-variables-in-classes,readability-identifier-naming)
83};
84
85using NodeId = int;
86using NodeIdMap = ArenaMap<const ir::AstNode *, NodeId>;
87
88class AssignAnalyzer : public BaseAnalyzer<AssignPendingExit> {
89public:
90    explicit AssignAnalyzer(ETSChecker *checker);
91    void Analyze(const ir::AstNode *node);
92
93    void MarkDead() override;
94
95private:
96    // node visitors
97    void AnalyzeNodes(const ir::AstNode *node);
98    void AnalyzeNode(const ir::AstNode *node);
99    bool AnalyzeStmtNode1(const ir::AstNode *node);
100    bool AnalyzeStmtNode2(const ir::AstNode *node);
101    bool AnalyzeExprNode1(const ir::AstNode *node);
102    bool AnalyzeExprNode2(const ir::AstNode *node);
103    void AnalyzeStat(const ir::AstNode *node);
104    void AnalyzeStats(const ArenaVector<ir::Statement *> &stats);
105    void AnalyzeBlock(const ir::BlockStatement *blockStmt);
106    void AnalyzeStructDecl(const ir::ETSStructDeclaration *structDecl);
107    void AnalyzeClassDecl(const ir::ClassDeclaration *classDecl);
108    void AnalyzeClassDef(const ir::ClassDefinition *classDef);
109    void ProcessClassDefStaticFields(const ir::ClassDefinition *classDef);
110    void CheckAnonymousClassCtor(const ir::ClassDefinition *classDef);
111    void AnalyzeMethodDef(const ir::MethodDefinition *methodDef);
112    void AnalyzeVarDef(const ir::VariableDeclaration *varDef);
113    void AnalyzeDoLoop(const ir::DoWhileStatement *doWhileStmt);
114    void AnalyzeWhileLoop(const ir::WhileStatement *whileStmt);
115    void AnalyzeForLoop(const ir::ForUpdateStatement *forStmt);
116    void AnalyzeForOfLoop(const ir::ForOfStatement *forOfStmt);
117    void AnalyzeIf(const ir::IfStatement *ifStmt);
118    void AnalyzeLabelled(const ir::LabelledStatement *labelledStmt);
119    void AnalyzeSwitch(const ir::SwitchStatement *switchStmt);
120    void AnalyzeTry(const ir::TryStatement *tryStmt);
121    void AnalyzeBreak(const ir::BreakStatement *breakStmt);
122    void AnalyzeContinue(const ir::ContinueStatement *contStmt);
123    void AnalyzeReturn(const ir::ReturnStatement *retStmt);
124    void AnalyzeThrow(const ir::ThrowStatement *throwStmt);
125    void AnalyzeAssert(const ir::AssertStatement *assertStmt);
126    void AnalyzeExpr(const ir::AstNode *node);
127    void AnalyzeExprs(const ArenaVector<ir::Expression *> &exprs);
128    void AnalyzeCond(const ir::AstNode *node);
129    void AnalyzeAssignExpr(const ir::AssignmentExpression *assignExpr);
130    void AnalyzeBinaryExpr(const ir::BinaryExpression *binExpr);
131    void AnalyzeCallExpr(const ir::CallExpression *callExpr);
132    void AnalyzeCondExpr(const ir::ConditionalExpression *condExpr);
133    void AnalyzeId(const ir::Identifier *id);
134    void AnalyzeMemberExpr(const ir::MemberExpression *membExpr);
135    void AnalyzeNewClass(const ir::ETSNewClassInstanceExpression *newClass);
136    void AnalyzeUnaryExpr(const ir::UnaryExpression *unaryExpr);
137    void AnalyzeUpdateExpr(const ir::UpdateExpression *updateExpr);
138    void AnalyzeArrowFunctionExpr(const ir::ArrowFunctionExpression *arrowFuncExpr);
139
140    // utils
141    void Warning(std::string_view message, const lexer::SourcePosition &pos);
142    void Warning(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos);
143    bool Trackable(const ir::AstNode *node) const;
144    bool IsConstUninitializedField(const ir::AstNode *node) const;
145    bool IsConstUninitializedStaticField(const ir::AstNode *node) const;
146    void NewVar(const ir::AstNode *node);
147    void LetInit(const ir::AstNode *node);
148    void CheckInit(const ir::AstNode *node);
149    void Split(bool setToNull);
150    void Merge();
151    void CheckPendingExits(bool inMethod);
152    NodeId GetNodeId(const ir::AstNode *node) const;
153    util::StringView GetVariableType(const ir::AstNode *node) const;
154    util::StringView GetVariableName(const ir::AstNode *node) const;
155    const lexer::SourcePosition &GetVariablePosition(const ir::AstNode *node) const;
156    const ir::AstNode *GetDeclaringNode(const ir::AstNode *node);
157    varbinder::Variable *GetBoundVariable(const ir::AstNode *node);
158    bool VariableHasDefaultValue(const ir::AstNode *node);
159
160    ETSChecker *checker_;
161    Set inits_ {};
162    Set uninits_ {};
163    Set uninitsTry_ {};
164    Set initsWhenTrue_ {};
165    Set initsWhenFalse_ {};
166    Set uninitsWhenTrue_ {};
167    Set uninitsWhenFalse_ {};
168    ArenaVector<const ir::AstNode *> varDecls_;
169    const ir::ClassDefinition *globalClass_ {};
170    const ir::ClassDefinition *classDef_ {};
171    bool globalClassIsVisited_ {};
172    int classFirstAdr_ {};
173    int firstNonGlobalAdr_ {};
174    int firstAdr_ {};
175    int nextAdr_ {};
176    int returnAdr_ {};
177    bool isInitialConstructor_ {};
178    NodeIdMap nodeIdMap_;
179    int numErrors_ {};
180    ArenaSet<const ir::AstNode *> foundErrors_;
181};
182
183}  // namespace ark::es2panda::checker
184
185#endif
186