13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#ifndef ES2PANDA_COMPILER_CHECKER_ETS_ASSIGN_ANALYZER_H
173af6ab5fSopenharmony_ci#define ES2PANDA_COMPILER_CHECKER_ETS_ASSIGN_ANALYZER_H
183af6ab5fSopenharmony_ci
193af6ab5fSopenharmony_ci#include "checker/ETSchecker.h"
203af6ab5fSopenharmony_ci#include "checker/ets/baseAnalyzer.h"
213af6ab5fSopenharmony_ci
223af6ab5fSopenharmony_ci#include "utils/arena_containers.h"
233af6ab5fSopenharmony_ci
243af6ab5fSopenharmony_cinamespace ark::es2panda::ir {
253af6ab5fSopenharmony_ciclass AstNode;
263af6ab5fSopenharmony_ci}  // namespace ark::es2panda::ir
273af6ab5fSopenharmony_ci
283af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_ciclass Set {
313af6ab5fSopenharmony_cipublic:
323af6ab5fSopenharmony_ci    Set() = default;
333af6ab5fSopenharmony_ci    ~Set() = default;
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_ci    DEFAULT_COPY_SEMANTIC(Set);
363af6ab5fSopenharmony_ci    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(Set);
373af6ab5fSopenharmony_ci
383af6ab5fSopenharmony_ci    void Reset();
393af6ab5fSopenharmony_ci    bool IsReset();
403af6ab5fSopenharmony_ci    void Incl(const int id);
413af6ab5fSopenharmony_ci    void InclRange(const int start, const int limit);
423af6ab5fSopenharmony_ci    void ExcludeFrom(const int start);
433af6ab5fSopenharmony_ci    void Excl(const int id);
443af6ab5fSopenharmony_ci    bool IsMember(const int id) const;
453af6ab5fSopenharmony_ci    Set &AndSet(const Set &xs);
463af6ab5fSopenharmony_ci    Set &OrSet(const Set &xs);
473af6ab5fSopenharmony_ci    Set &DiffSet(const Set &xs);
483af6ab5fSopenharmony_ci    int Next(const int id);
493af6ab5fSopenharmony_ci
503af6ab5fSopenharmony_ciprotected:
513af6ab5fSopenharmony_ci    void InternalAndSet(const Set &xs);
523af6ab5fSopenharmony_ci
533af6ab5fSopenharmony_ciprivate:
543af6ab5fSopenharmony_ci    bool reset_ {};
553af6ab5fSopenharmony_ci    std::set<int> nodes_ {};
563af6ab5fSopenharmony_ci};
573af6ab5fSopenharmony_ci
583af6ab5fSopenharmony_ciclass AssignPendingExit : public PendingExit {
593af6ab5fSopenharmony_cipublic:
603af6ab5fSopenharmony_ci    explicit AssignPendingExit(const ir::AstNode *node, Set &inits, Set &uninits)
613af6ab5fSopenharmony_ci        : PendingExit(node), inits_(&inits), uninits_(&uninits)
623af6ab5fSopenharmony_ci    {
633af6ab5fSopenharmony_ci        exitInits_ = inits;
643af6ab5fSopenharmony_ci        exitUninits_ = uninits;
653af6ab5fSopenharmony_ci    }
663af6ab5fSopenharmony_ci    ~AssignPendingExit() override = default;
673af6ab5fSopenharmony_ci
683af6ab5fSopenharmony_ci    DEFAULT_COPY_SEMANTIC(AssignPendingExit);
693af6ab5fSopenharmony_ci    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(AssignPendingExit);
703af6ab5fSopenharmony_ci
713af6ab5fSopenharmony_ci    void ResolveJump() override
723af6ab5fSopenharmony_ci    {
733af6ab5fSopenharmony_ci        inits_->AndSet(exitInits_);
743af6ab5fSopenharmony_ci        uninits_->AndSet(exitUninits_);
753af6ab5fSopenharmony_ci    }
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ci    // NOLINTBEGIN(misc-non-private-member-variables-in-classes,readability-identifier-naming)
783af6ab5fSopenharmony_ci    Set *inits_;
793af6ab5fSopenharmony_ci    Set *uninits_;
803af6ab5fSopenharmony_ci    Set exitInits_;
813af6ab5fSopenharmony_ci    Set exitUninits_;
823af6ab5fSopenharmony_ci    // NOLINTEND(misc-non-private-member-variables-in-classes,readability-identifier-naming)
833af6ab5fSopenharmony_ci};
843af6ab5fSopenharmony_ci
853af6ab5fSopenharmony_ciusing NodeId = int;
863af6ab5fSopenharmony_ciusing NodeIdMap = ArenaMap<const ir::AstNode *, NodeId>;
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ciclass AssignAnalyzer : public BaseAnalyzer<AssignPendingExit> {
893af6ab5fSopenharmony_cipublic:
903af6ab5fSopenharmony_ci    explicit AssignAnalyzer(ETSChecker *checker);
913af6ab5fSopenharmony_ci    void Analyze(const ir::AstNode *node);
923af6ab5fSopenharmony_ci
933af6ab5fSopenharmony_ci    void MarkDead() override;
943af6ab5fSopenharmony_ci
953af6ab5fSopenharmony_ciprivate:
963af6ab5fSopenharmony_ci    // node visitors
973af6ab5fSopenharmony_ci    void AnalyzeNodes(const ir::AstNode *node);
983af6ab5fSopenharmony_ci    void AnalyzeNode(const ir::AstNode *node);
993af6ab5fSopenharmony_ci    bool AnalyzeStmtNode1(const ir::AstNode *node);
1003af6ab5fSopenharmony_ci    bool AnalyzeStmtNode2(const ir::AstNode *node);
1013af6ab5fSopenharmony_ci    bool AnalyzeExprNode1(const ir::AstNode *node);
1023af6ab5fSopenharmony_ci    bool AnalyzeExprNode2(const ir::AstNode *node);
1033af6ab5fSopenharmony_ci    void AnalyzeStat(const ir::AstNode *node);
1043af6ab5fSopenharmony_ci    void AnalyzeStats(const ArenaVector<ir::Statement *> &stats);
1053af6ab5fSopenharmony_ci    void AnalyzeBlock(const ir::BlockStatement *blockStmt);
1063af6ab5fSopenharmony_ci    void AnalyzeStructDecl(const ir::ETSStructDeclaration *structDecl);
1073af6ab5fSopenharmony_ci    void AnalyzeClassDecl(const ir::ClassDeclaration *classDecl);
1083af6ab5fSopenharmony_ci    void AnalyzeClassDef(const ir::ClassDefinition *classDef);
1093af6ab5fSopenharmony_ci    void ProcessClassDefStaticFields(const ir::ClassDefinition *classDef);
1103af6ab5fSopenharmony_ci    void CheckAnonymousClassCtor(const ir::ClassDefinition *classDef);
1113af6ab5fSopenharmony_ci    void AnalyzeMethodDef(const ir::MethodDefinition *methodDef);
1123af6ab5fSopenharmony_ci    void AnalyzeVarDef(const ir::VariableDeclaration *varDef);
1133af6ab5fSopenharmony_ci    void AnalyzeDoLoop(const ir::DoWhileStatement *doWhileStmt);
1143af6ab5fSopenharmony_ci    void AnalyzeWhileLoop(const ir::WhileStatement *whileStmt);
1153af6ab5fSopenharmony_ci    void AnalyzeForLoop(const ir::ForUpdateStatement *forStmt);
1163af6ab5fSopenharmony_ci    void AnalyzeForOfLoop(const ir::ForOfStatement *forOfStmt);
1173af6ab5fSopenharmony_ci    void AnalyzeIf(const ir::IfStatement *ifStmt);
1183af6ab5fSopenharmony_ci    void AnalyzeLabelled(const ir::LabelledStatement *labelledStmt);
1193af6ab5fSopenharmony_ci    void AnalyzeSwitch(const ir::SwitchStatement *switchStmt);
1203af6ab5fSopenharmony_ci    void AnalyzeTry(const ir::TryStatement *tryStmt);
1213af6ab5fSopenharmony_ci    void AnalyzeBreak(const ir::BreakStatement *breakStmt);
1223af6ab5fSopenharmony_ci    void AnalyzeContinue(const ir::ContinueStatement *contStmt);
1233af6ab5fSopenharmony_ci    void AnalyzeReturn(const ir::ReturnStatement *retStmt);
1243af6ab5fSopenharmony_ci    void AnalyzeThrow(const ir::ThrowStatement *throwStmt);
1253af6ab5fSopenharmony_ci    void AnalyzeAssert(const ir::AssertStatement *assertStmt);
1263af6ab5fSopenharmony_ci    void AnalyzeExpr(const ir::AstNode *node);
1273af6ab5fSopenharmony_ci    void AnalyzeExprs(const ArenaVector<ir::Expression *> &exprs);
1283af6ab5fSopenharmony_ci    void AnalyzeCond(const ir::AstNode *node);
1293af6ab5fSopenharmony_ci    void AnalyzeAssignExpr(const ir::AssignmentExpression *assignExpr);
1303af6ab5fSopenharmony_ci    void AnalyzeBinaryExpr(const ir::BinaryExpression *binExpr);
1313af6ab5fSopenharmony_ci    void AnalyzeCallExpr(const ir::CallExpression *callExpr);
1323af6ab5fSopenharmony_ci    void AnalyzeCondExpr(const ir::ConditionalExpression *condExpr);
1333af6ab5fSopenharmony_ci    void AnalyzeId(const ir::Identifier *id);
1343af6ab5fSopenharmony_ci    void AnalyzeMemberExpr(const ir::MemberExpression *membExpr);
1353af6ab5fSopenharmony_ci    void AnalyzeNewClass(const ir::ETSNewClassInstanceExpression *newClass);
1363af6ab5fSopenharmony_ci    void AnalyzeUnaryExpr(const ir::UnaryExpression *unaryExpr);
1373af6ab5fSopenharmony_ci    void AnalyzeUpdateExpr(const ir::UpdateExpression *updateExpr);
1383af6ab5fSopenharmony_ci    void AnalyzeArrowFunctionExpr(const ir::ArrowFunctionExpression *arrowFuncExpr);
1393af6ab5fSopenharmony_ci
1403af6ab5fSopenharmony_ci    // utils
1413af6ab5fSopenharmony_ci    void Warning(std::string_view message, const lexer::SourcePosition &pos);
1423af6ab5fSopenharmony_ci    void Warning(std::initializer_list<TypeErrorMessageElement> list, const lexer::SourcePosition &pos);
1433af6ab5fSopenharmony_ci    bool Trackable(const ir::AstNode *node) const;
1443af6ab5fSopenharmony_ci    bool IsConstUninitializedField(const ir::AstNode *node) const;
1453af6ab5fSopenharmony_ci    bool IsConstUninitializedStaticField(const ir::AstNode *node) const;
1463af6ab5fSopenharmony_ci    void NewVar(const ir::AstNode *node);
1473af6ab5fSopenharmony_ci    void LetInit(const ir::AstNode *node);
1483af6ab5fSopenharmony_ci    void CheckInit(const ir::AstNode *node);
1493af6ab5fSopenharmony_ci    void Split(bool setToNull);
1503af6ab5fSopenharmony_ci    void Merge();
1513af6ab5fSopenharmony_ci    void CheckPendingExits(bool inMethod);
1523af6ab5fSopenharmony_ci    NodeId GetNodeId(const ir::AstNode *node) const;
1533af6ab5fSopenharmony_ci    util::StringView GetVariableType(const ir::AstNode *node) const;
1543af6ab5fSopenharmony_ci    util::StringView GetVariableName(const ir::AstNode *node) const;
1553af6ab5fSopenharmony_ci    const lexer::SourcePosition &GetVariablePosition(const ir::AstNode *node) const;
1563af6ab5fSopenharmony_ci    const ir::AstNode *GetDeclaringNode(const ir::AstNode *node);
1573af6ab5fSopenharmony_ci    varbinder::Variable *GetBoundVariable(const ir::AstNode *node);
1583af6ab5fSopenharmony_ci    bool VariableHasDefaultValue(const ir::AstNode *node);
1593af6ab5fSopenharmony_ci
1603af6ab5fSopenharmony_ci    ETSChecker *checker_;
1613af6ab5fSopenharmony_ci    Set inits_ {};
1623af6ab5fSopenharmony_ci    Set uninits_ {};
1633af6ab5fSopenharmony_ci    Set uninitsTry_ {};
1643af6ab5fSopenharmony_ci    Set initsWhenTrue_ {};
1653af6ab5fSopenharmony_ci    Set initsWhenFalse_ {};
1663af6ab5fSopenharmony_ci    Set uninitsWhenTrue_ {};
1673af6ab5fSopenharmony_ci    Set uninitsWhenFalse_ {};
1683af6ab5fSopenharmony_ci    ArenaVector<const ir::AstNode *> varDecls_;
1693af6ab5fSopenharmony_ci    const ir::ClassDefinition *globalClass_ {};
1703af6ab5fSopenharmony_ci    const ir::ClassDefinition *classDef_ {};
1713af6ab5fSopenharmony_ci    bool globalClassIsVisited_ {};
1723af6ab5fSopenharmony_ci    int classFirstAdr_ {};
1733af6ab5fSopenharmony_ci    int firstNonGlobalAdr_ {};
1743af6ab5fSopenharmony_ci    int firstAdr_ {};
1753af6ab5fSopenharmony_ci    int nextAdr_ {};
1763af6ab5fSopenharmony_ci    int returnAdr_ {};
1773af6ab5fSopenharmony_ci    bool isInitialConstructor_ {};
1783af6ab5fSopenharmony_ci    NodeIdMap nodeIdMap_;
1793af6ab5fSopenharmony_ci    int numErrors_ {};
1803af6ab5fSopenharmony_ci    ArenaSet<const ir::AstNode *> foundErrors_;
1813af6ab5fSopenharmony_ci};
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_ci#endif
186