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 
24 namespace ark::es2panda::ir {
25 class AstNode;
26 }  // namespace ark::es2panda::ir
27 
28 namespace ark::es2panda::checker {
29 
30 class Set {
31 public:
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 
50 protected:
51     void InternalAndSet(const Set &xs);
52 
53 private:
54     bool reset_ {};
55     std::set<int> nodes_ {};
56 };
57 
58 class AssignPendingExit : public PendingExit {
59 public:
AssignPendingExit(const ir::AstNode *node, Set &inits, Set &uninits)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 
85 using NodeId = int;
86 using NodeIdMap = ArenaMap<const ir::AstNode *, NodeId>;
87 
88 class AssignAnalyzer : public BaseAnalyzer<AssignPendingExit> {
89 public:
90     explicit AssignAnalyzer(ETSChecker *checker);
91     void Analyze(const ir::AstNode *node);
92 
93     void MarkDead() override;
94 
95 private:
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