1/*
2 * Copyright (c) 2021 - 2023 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_CORE_ENV_SCOPE_H
17#define ES2PANDA_COMPILER_CORE_ENV_SCOPE_H
18
19#include "varbinder/scope.h"
20#include "ir/irnode.h"
21#include "compiler/core/dynamicContext.h"
22#include "compiler/core/regScope.h"
23#include "compiler/core/labelTarget.h"
24
25namespace ark::es2panda::ir {
26class AstNode;
27class Statement;
28}  // namespace ark::es2panda::ir
29
30namespace ark::es2panda::compiler {
31class PandaGen;
32
33class ScopeContext {
34public:
35    explicit ScopeContext(CodeGen *cg, varbinder::Scope *newScope);
36    ~ScopeContext();
37
38    NO_COPY_SEMANTIC(ScopeContext);
39    NO_MOVE_SEMANTIC(ScopeContext);
40
41private:
42    CodeGen *cg_;
43    varbinder::Scope *prevScope_;
44};
45
46class EnvScope {
47public:
48    explicit EnvScope() = default;
49
50    NO_COPY_SEMANTIC(EnvScope);
51    NO_MOVE_SEMANTIC(EnvScope);
52    ~EnvScope();
53
54    void Initialize(PandaGen *pg, VReg lexEnv);
55
56    VReg LexEnv() const
57    {
58        return lexEnv_;
59    }
60
61    EnvScope *Prev() const
62    {
63        return prev_;
64    }
65
66protected:
67    friend class PandaGen;
68
69    // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
70    PandaGen *pg_ {};
71    EnvScope *prev_ {};
72    VReg lexEnv_ {};
73    // NOLINTEND(misc-non-private-member-variables-in-classes)
74};
75
76class LoopEnvScope : public EnvScope {
77public:
78    explicit LoopEnvScope(PandaGen *pg, varbinder::LoopScope *scope, LabelTarget target)
79        : scope_(NeedEnv(scope) ? scope : nullptr), regScope_(pg, scope), lexEnvCtx_(this, pg, target)
80    {
81        CopyBindings(pg, scope, varbinder::VariableFlags::PER_ITERATION);
82    }
83
84    explicit LoopEnvScope(PandaGen *pg, LabelTarget target, varbinder::LoopScope *scope)
85        : scope_(NeedEnv(scope) ? scope : nullptr), regScope_(pg), lexEnvCtx_(this, pg, target)
86    {
87        CopyBindings(pg, scope, varbinder::VariableFlags::PER_ITERATION);
88    }
89
90    explicit LoopEnvScope(PandaGen *pg, varbinder::LoopDeclarationScope *scope)
91        : scope_(NeedEnv(scope) ? scope : nullptr), regScope_(pg), lexEnvCtx_(this, pg, {})
92    {
93        CopyBindings(pg, scope, varbinder::VariableFlags::LOOP_DECL);
94    }
95
96    varbinder::VariableScope *Scope() const
97    {
98        ASSERT(HasEnv());
99        return scope_;
100    }
101
102    bool HasEnv() const
103    {
104        return scope_ != nullptr;
105    }
106
107    void CopyPetIterationCtx();
108
109private:
110    static bool NeedEnv(varbinder::VariableScope *scope)
111    {
112        return scope->IsVariableScope() && scope->AsVariableScope()->NeedLexEnv();
113    }
114
115    void CopyBindings(PandaGen *pg, varbinder::VariableScope *scope, varbinder::VariableFlags flag);
116
117    varbinder::VariableScope *scope_ {};
118    LocalRegScope regScope_;
119    LexEnvContext lexEnvCtx_;
120};
121}  // namespace ark::es2panda::compiler
122
123#endif
124